// Copyright (c) 2016, 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 'graph_builder.dart';
import 'nodes.dart';
import '../closure.dart';
import '../common.dart';
import '../elements/resolution_types.dart';
import '../types/types.dart';
import '../elements/elements.dart';
import '../io/source_information.dart';
import '../universe/use.dart' show TypeUse;

/// Functions to insert type checking, coercion, and instruction insertion
/// depending on the environment for dart code.
class TypeBuilder {
  final GraphBuilder builder;
  TypeBuilder(this.builder);

  /// Create an instruction to simply trust the provided type.
  HInstruction _trustType(HInstruction original, ResolutionDartType type) {
    assert(builder.compiler.options.trustTypeAnnotations);
    assert(type != null);
    type = builder.localsHandler.substInContext(type);
    type = type.unaliased;
    if (type.isDynamic) return original;
    if (!type.isInterfaceType) return original;
    if (type.isObject) return original;
    // The type element is either a class or the void element.
    ClassElement element = type.element;
    TypeMask mask = new TypeMask.subtype(element, builder.closedWorld);
    return new HTypeKnown.pinned(mask, original);
  }

  /// Produces code that checks the runtime type is actually the type specified
  /// by attempting a type conversion.
  HInstruction _checkType(
      HInstruction original, ResolutionDartType type, int kind) {
    assert(builder.compiler.options.enableTypeAssertions);
    assert(type != null);
    type = builder.localsHandler.substInContext(type);
    HInstruction other = buildTypeConversion(original, type, kind);
    // TODO(johnniwinther): This operation on `registry` may be inconsistent.
    // If it is needed then it seems likely that similar invocations of
    // `buildTypeConversion` in `SsaBuilder.visitAs` should also be followed by
    // a similar operation on `registry`; otherwise, this one might not be
    // needed.
    builder.registry?.registerTypeUse(new TypeUse.isCheck(type));
    return other;
  }

  /// Depending on the context and the mode, wrap the given type in an
  /// instruction that checks the type is what we expect or automatically
  /// trusts the written type.
  HInstruction potentiallyCheckOrTrustType(
      HInstruction original, ResolutionDartType type,
      {int kind: HTypeConversion.CHECKED_MODE_CHECK}) {
    if (type == null) return original;
    HInstruction checkedOrTrusted = original;
    if (builder.compiler.options.trustTypeAnnotations) {
      checkedOrTrusted = _trustType(original, type);
    } else if (builder.compiler.options.enableTypeAssertions) {
      checkedOrTrusted = _checkType(original, type, kind);
    }
    if (checkedOrTrusted == original) return original;
    builder.add(checkedOrTrusted);
    return checkedOrTrusted;
  }

  /// Helper to create an instruction that gets the value of a type variable.
  HInstruction addTypeVariableReference(
      ResolutionTypeVariableType type, Element member,
      {SourceInformation sourceInformation}) {
    assert(assertTypeInContext(type));
    if (type is MethodTypeVariableType) {
      return builder.graph.addConstantNull(builder.closedWorld);
    }
    bool isClosure = member.enclosingElement.isClosure;
    if (isClosure) {
      ClosureClassElement closureClass = member.enclosingElement;
      member = closureClass.methodElement;
      member = member.outermostEnclosingMemberOrTopLevel;
    }
    bool isInConstructorContext =
        member.isConstructor || member.isGenerativeConstructorBody;
    Local typeVariableLocal =
        builder.localsHandler.getTypeVariableAsLocal(type);
    if (isClosure) {
      if (member.isFactoryConstructor ||
          (isInConstructorContext &&
              builder.hasDirectLocal(typeVariableLocal))) {
        // The type variable is used from a closure in a factory constructor.
        // The value of the type argument is stored as a local on the closure
        // itself.
        return builder.localsHandler
            .readLocal(typeVariableLocal, sourceInformation: sourceInformation);
      } else if (member.isFunction ||
          member.isGetter ||
          member.isSetter ||
          isInConstructorContext) {
        // The type variable is stored on the "enclosing object" and needs to be
        // accessed using the this-reference in the closure.
        return readTypeVariable(type, member,
            sourceInformation: sourceInformation);
      } else {
        assert(member.isField);
        // The type variable is stored in a parameter of the method.
        return builder.localsHandler.readLocal(typeVariableLocal);
      }
    } else if (isInConstructorContext ||
        // When [member] is a field, we can be either
        // generating a checked setter or inlining its
        // initializer in a constructor. An initializer is
        // never built standalone, so in that case [target] is not
        // the [member] itself.
        (member.isField && member != builder.targetElement)) {
      // The type variable is stored in a parameter of the method.
      return builder.localsHandler
          .readLocal(typeVariableLocal, sourceInformation: sourceInformation);
    } else if (member.isInstanceMember) {
      // The type variable is stored on the object.
      return readTypeVariable(type, member,
          sourceInformation: sourceInformation);
    } else {
      builder.compiler.reporter.internalError(
          type.element, 'Unexpected type variable in static context.');
      return null;
    }
  }

  /// Generate code to extract the type argument from the object.
  HInstruction readTypeVariable(
      ResolutionTypeVariableType variable, Element member,
      {SourceInformation sourceInformation}) {
    assert(member.isInstanceMember);
    assert(variable is! MethodTypeVariableType);
    HInstruction target = builder.localsHandler.readThis();
    builder.push(new HTypeInfoReadVariable(
        variable, target, builder.commonMasks.dynamicType)
      ..sourceInformation = sourceInformation);
    return builder.pop();
  }

  HInstruction buildTypeArgumentRepresentations(
      ResolutionDartType type, Element sourceElement) {
    assert(!type.isTypeVariable);
    // Compute the representation of the type arguments, including access
    // to the runtime type information for type variables as instructions.
    assert(type.element.isClass);
    ResolutionInterfaceType interface = type;
    List<HInstruction> inputs = <HInstruction>[];
    for (ResolutionDartType argument in interface.typeArguments) {
      inputs.add(analyzeTypeArgument(argument, sourceElement));
    }
    HInstruction representation = new HTypeInfoExpression(
        TypeInfoExpressionKind.INSTANCE,
        interface.element.thisType,
        inputs,
        builder.commonMasks.dynamicType);
    return representation;
  }

  /// Check that [type] is valid in the context of `localsHandler.contextClass`.
  /// This should only be called in assertions.
  bool assertTypeInContext(ResolutionDartType type, [Spannable spannable]) {
    return invariant(spannable == null ? CURRENT_ELEMENT_SPANNABLE : spannable,
        () {
      ClassElement contextClass = Types.getClassContext(type);
      return contextClass == null ||
          contextClass == builder.localsHandler.contextClass;
    },
        message: "Type '$type' is not valid context of "
            "${builder.localsHandler.contextClass}.");
  }

  HInstruction analyzeTypeArgument(
      ResolutionDartType argument, Element sourceElement,
      {SourceInformation sourceInformation}) {
    assert(assertTypeInContext(argument));
    argument = argument.unaliased;
    if (argument.treatAsDynamic) {
      // Represent [dynamic] as [null].
      return builder.graph.addConstantNull(builder.closedWorld);
    }

    if (argument.isTypeVariable) {
      return addTypeVariableReference(argument, sourceElement,
          sourceInformation: sourceInformation);
    }

    List<HInstruction> inputs = <HInstruction>[];
    argument.forEachTypeVariable((variable) {
      if (variable is! MethodTypeVariableType) {
        inputs.add(analyzeTypeArgument(variable, sourceElement));
      }
    });
    HInstruction result = new HTypeInfoExpression(
        TypeInfoExpressionKind.COMPLETE,
        argument,
        inputs,
        builder.commonMasks.dynamicType)..sourceInformation = sourceInformation;
    builder.add(result);
    return result;
  }

  /// In checked mode, generate type tests for the parameters of the inlined
  /// function.
  void potentiallyCheckInlinedParameterTypes(FunctionElement function) {
    if (!checkOrTrustTypes) return;

    FunctionSignature signature = function.functionSignature;
    signature.orderedForEachParameter((ParameterElement parameter) {
      HInstruction argument = builder.localsHandler.readLocal(parameter);
      potentiallyCheckOrTrustType(argument, parameter.type);
    });
  }

  bool get checkOrTrustTypes =>
      builder.compiler.options.enableTypeAssertions ||
      builder.compiler.options.trustTypeAnnotations;

  /// Build a [HTypeConversion] for converting [original] to type [type].
  ///
  /// Invariant: [type] must be valid in the context.
  /// See [LocalsHandler.substInContext].
  HInstruction buildTypeConversion(
      HInstruction original, ResolutionDartType type, int kind) {
    if (type == null) return original;
    // GENERIC_METHODS: The following statement was added for parsing and
    // ignoring method type variables; must be generalized for full support of
    // generic methods.
    type = type.dynamifyMethodTypeVariableType;
    type = type.unaliased;
    assert(assertTypeInContext(type, original));
    if (type.isInterfaceType && !type.treatAsRaw) {
      ResolutionInterfaceType interfaceType = type;
      TypeMask subtype =
          new TypeMask.subtype(interfaceType.element, builder.closedWorld);
      HInstruction representations =
          buildTypeArgumentRepresentations(type, builder.sourceElement);
      builder.add(representations);
      return new HTypeConversion.withTypeRepresentation(
          type, kind, subtype, original, representations);
    } else if (type.isTypeVariable) {
      TypeMask subtype = original.instructionType;
      HInstruction typeVariable =
          addTypeVariableReference(type, builder.sourceElement);
      return new HTypeConversion.withTypeRepresentation(
          type, kind, subtype, original, typeVariable);
    } else if (type.isFunctionType) {
      return builder.buildFunctionTypeConversion(original, type, kind);
    } else {
      return original.convertType(builder.closedWorld, type, kind);
    }
  }
}
