// Copyright (c) 2022, 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';

// Extend references with flags to more easily identify getters and setters.

extension GetterSetterReference on Reference {
  bool get isImplicitGetter {
    Member member = asMember;
    return member is Field && member.getterReference == this;
  }

  bool get isImplicitSetter {
    Member member = asMember;
    if (member is Field) {
      if (member.setterReference == this) return true;
      if (member.isInstanceMember) {
        return _isUncheckedEntrySetterReference ||
            _isCheckedEntrySetterReference;
      }
    }
    return false;
  }

  bool get isGetter {
    Member member = asMember;
    return (member is Procedure && member.isGetter) || isImplicitGetter;
  }

  bool get isSetter {
    Member member = asMember;
    return (member is Procedure && member.isSetter) || isImplicitSetter;
  }
}

// Extend procedures with a tearOffReference that refers to the tear-off
// implementation for that procedure. This enables a Reference to refer to any
// implementation relating to a member, including its tear-off, which it can't
// do in plain kernel.

// Use Expandos to avoid keeping the procedure alive.
final Expando<Reference> _tearOffReference = Expando();
final Expando<Reference> _typeCheckerReference = Expando();
final Expando<Reference> _checkedEntryReferences = Expando();
final Expando<Reference> _uncheckedEntryReferences = Expando();
final Expando<Reference> _bodyReferences = Expando();
final Expando<Reference> _initializerReference = Expando();
final Expando<Reference> _constructorBodyReference = Expando();

extension CustomReference on Member {
  Reference get tearOffReference =>
      _tearOffReference[this] ??= Reference()..node = this;

  Reference get typeCheckerReference =>
      _typeCheckerReference[this] ??= Reference()..node = this;

  Reference get checkedEntryReference {
    assert(_memberCanHaveMultipleEntryPoints(this));
    return _checkedEntryReferences[this] ??= Reference()..node = this;
  }

  Reference get uncheckedEntryReference {
    assert(_memberCanHaveMultipleEntryPoints(this));
    return _uncheckedEntryReferences[this] ??= Reference()..node = this;
  }

  Reference get bodyReference {
    assert(_memberCanHaveMultipleEntryPoints(this));
    return _bodyReferences[this] ??= Reference()..node = this;
  }

  Reference get initializerReference =>
      _initializerReference[this] ??= Reference()..node = this;

  Reference get constructorBodyReference =>
      _constructorBodyReference[this] ??= Reference()..node = this;
}

extension IsCustomReference on Reference {
  bool get isTearOffReference => _tearOffReference[asMember] == this;

  bool get isTypeCheckerReference => _typeCheckerReference[asMember] == this;

  bool get isCheckedEntryReference => _checkedEntryReferences[asMember] == this;

  bool get _isCheckedEntrySetterReference =>
      (asMember is Field) && isCheckedEntryReference;

  bool get isUncheckedEntryReference =>
      _uncheckedEntryReferences[asMember] == this;

  bool get _isUncheckedEntrySetterReference =>
      (asMember is Field) && isUncheckedEntryReference;

  bool get isBodyReference => _bodyReferences[asMember] == this;

  bool get isInitializerReference => _initializerReference[asMember] == this;

  bool get isConstructorBodyReference =>
      _constructorBodyReference[asMember] == this;

  EntryPoint get entryKind {
    if (isUncheckedEntryReference) {
      return EntryPoint.unchecked;
    }
    if (isCheckedEntryReference) {
      return EntryPoint.checked;
    }
    if (isBodyReference) {
      return EntryPoint.body;
    }
    return EntryPoint.normal;
  }
}

extension ReferenceAs on Member {
  Reference referenceAs({required bool getter, required bool setter}) {
    assert(!getter || !setter); // members cannot be both setter and getter
    Member member = this;
    return member is Field
        ? setter
            ? member.setterReference!
            : member.getterReference
        : getter && member is Procedure && member.kind == ProcedureKind.Method
            ? member.tearOffReference
            : member.reference;
  }
}

// Sanity check that [member] may have multiple entry points.
bool _memberCanHaveMultipleEntryPoints(Member member) {
  if (member is Field && member.hasSetter ||
      member is Procedure && member.isSetter) {
    // The unchecked entry will bypass type checks on the setter values.
    return true;
  }
  if (member is Procedure &&
      const [ProcedureKind.Method, ProcedureKind.Operator]
          .contains(member.kind) &&
      (member.function.positionalParameters.isNotEmpty ||
          member.function.namedParameters.isNotEmpty ||
          member.function.typeParameters.isNotEmpty)) {
    // The unchecked entry will bypass type checks on the method.
    return true;
  }
  return false;
}

enum EntryPoint {
  // A single procedure doing type argument checks, optional argument handling
  // and the body.
  normal,
  // A entry function doing type argument checks, optional argument handling but
  // delegates to the actual [body] function.
  checked,
  // A entry function doing optional argument handling but
  // delegates to the actual [body] function.
  unchecked,
  // The body of a function excluding type checks and optional argument
  // handling.
  body,
}
