// Copyright (c) 2012, 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.

library;

import '../common.dart';
import '../common/codegen.dart';
import '../common/tasks.dart';
import '../elements/entities.dart';
import '../inferrer/types.dart';
import '../js_model/elements.dart';
import 'annotations.dart';
import 'codegen_inputs.dart';

abstract class FunctionCompiler {
  void initialize(
    GlobalTypeInferenceResults globalInferenceResults,
    CodegenInputs codegen,
  );

  /// Generates JavaScript code for [member].
  CodegenResult compile(MemberEntity member);

  List<CompilerTask> get tasks;
}

enum _Decision {
  unknown,
  mustNotInline,
  mayInlineInLoopMustNotOutside,
  canInlineInLoopMustNotOutside,
  canInlineInLoopMayInlineOutside,
  canInline,
}

/*
 * Invariants:
 *   canInline(function) implies canInline(function, insideLoop:true)
 *   !canInline(function, insideLoop: true) implies !canInline(function)
 */
class FunctionInlineCache {
  final AnnotationsData _annotationsData;

  final Map<FunctionEntity, _Decision> _cachedDecisions = {};

  FunctionInlineCache(this._annotationsData);

  /// Checks that [method] is the canonical representative for this method.
  ///
  /// For a [MethodElement] this means it must be the declaration element.
  bool checkFunction(FunctionEntity method) {
    return '$method'.startsWith(jsElementPrefix);
  }

  // Returns `true`/`false` if we have a cached decision.
  // Returns `null` otherwise.
  bool? canInline(FunctionEntity element, {required bool insideLoop}) {
    assert(checkFunction(element), failedAt(element));

    // TODO(sra): Have annotations for mustInline / noInline for constructor
    // bodies. (There used to be some logic here to have constructor bodies,
    // inherit the settings from annotations on the generative
    // constructor. This was conflated with the heuristic decisions, leading
    // to lack of inlining where it was beneficial.)

    final decision = _cachedDecisions[element] ?? _Decision.unknown;

    if (insideLoop) {
      switch (decision) {
        case _Decision.mustNotInline:
          return false;

        case _Decision.unknown:
        case _Decision.mayInlineInLoopMustNotOutside:
          // We know we can't inline outside a loop, but don't know for the
          // loop case. Return `null` to indicate that we don't know yet.
          return null;

        case _Decision.canInlineInLoopMustNotOutside:
        case _Decision.canInlineInLoopMayInlineOutside:
        case _Decision.canInline:
          return true;
      }
    } else {
      switch (decision) {
        case _Decision.mustNotInline:
        case _Decision.mayInlineInLoopMustNotOutside:
        case _Decision.canInlineInLoopMustNotOutside:
          return false;

        case _Decision.unknown:
        case _Decision.canInlineInLoopMayInlineOutside:
          // We know we can inline inside a loop, but don't know for the
          // non-loop case. Return `null` to indicate that we don't know yet.
          return null;

        case _Decision.canInline:
          return true;
      }
    }
  }

  void markAsInlinable(FunctionEntity element, {required bool insideLoop}) {
    assert(checkFunction(element), failedAt(element));
    final oldDecision = _cachedDecisions[element] ?? _Decision.unknown;

    if (insideLoop) {
      switch (oldDecision) {
        case _Decision.mustNotInline:
          throw failedAt(
            element,
            "Can't mark $element as non-inlinable and inlinable at the "
            "same time.",
          );

        case _Decision.unknown:
          // We know that it can be inlined in a loop, but don't know about the
          // non-loop case yet.
          _cachedDecisions[element] = _Decision.canInlineInLoopMayInlineOutside;
          break;

        case _Decision.mayInlineInLoopMustNotOutside:
          _cachedDecisions[element] = _Decision.canInlineInLoopMustNotOutside;
          break;

        case _Decision.canInlineInLoopMustNotOutside:
        case _Decision.canInlineInLoopMayInlineOutside:
        case _Decision.canInline:
          // Do nothing.
          break;
      }
    } else {
      switch (oldDecision) {
        case _Decision.mustNotInline:
        case _Decision.mayInlineInLoopMustNotOutside:
        case _Decision.canInlineInLoopMustNotOutside:
          throw failedAt(
            element,
            "Can't mark $element as non-inlinable and inlinable at the "
            "same time.",
          );

        case _Decision.unknown:
        case _Decision.canInlineInLoopMayInlineOutside:
          _cachedDecisions[element] = _Decision.canInline;
          break;

        case _Decision.canInline:
          // Do nothing.
          break;
      }
    }
  }

  void markAsNonInlinable(FunctionEntity element, {bool insideLoop = true}) {
    assert(checkFunction(element), failedAt(element));
    final oldDecision = _cachedDecisions[element] ?? _Decision.unknown;

    if (insideLoop) {
      switch (oldDecision) {
        case _Decision.canInlineInLoopMustNotOutside:
        case _Decision.canInlineInLoopMayInlineOutside:
        case _Decision.canInline:
          throw failedAt(
            element,
            "Can't mark $element as non-inlinable and inlinable at the "
            "same time.",
          );

        case _Decision.mayInlineInLoopMustNotOutside:
        case _Decision.unknown:
          _cachedDecisions[element] = _Decision.mustNotInline;
          break;

        case _Decision.mustNotInline:
          // Do nothing.
          break;
      }
    } else {
      switch (oldDecision) {
        case _Decision.canInline:
          throw failedAt(
            element,
            "Can't mark $element as non-inlinable and inlinable at the "
            "same time.",
          );

        case _Decision.unknown:
          // We can't inline outside a loop, but we might still be allowed to do
          // so outside.
          _cachedDecisions[element] = _Decision.mayInlineInLoopMustNotOutside;
          break;

        case _Decision.canInlineInLoopMayInlineOutside:
          // We already knew that the function could be inlined inside a loop,
          // but didn't have information about the non-loop case. Now we know
          // that it can't be inlined outside a loop.
          _cachedDecisions[element] = _Decision.canInlineInLoopMustNotOutside;
          break;

        case _Decision.mayInlineInLoopMustNotOutside:
        case _Decision.canInlineInLoopMustNotOutside:
        case _Decision.mustNotInline:
          // Do nothing.
          break;
      }
    }
  }

  bool markedAsNoInline(FunctionEntity element) {
    assert(checkFunction(element), failedAt(element));
    return _annotationsData.hasNoInline(element);
  }

  bool markedAsTryInline(FunctionEntity element) {
    assert(checkFunction(element), failedAt(element));
    return _annotationsData.hasTryInline(element);
  }
}
