// 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.

library vm.transformations.no_dynamic_invocations_annotator;

import 'package:kernel/ast.dart';

import '../metadata/procedure_attributes.dart';

/// Assumes strong mode and closed world. If a procedure can not be riched
/// via dynamic invocation from anywhere then annotates it with appropriate
/// [ProcedureAttributeMetadata] annotation.
Component transformComponent(Component component) {
  new NoDynamicUsesAnnotator(component).visitComponent(component);
  return component;
}

enum Action { get, set, invoke }

class Selector {
  final Action action;
  final Name target;

  Selector(this.action, this.target);

  Selector.doInvoke(Name target) : this(Action.invoke, target);
  Selector.doGet(Name target) : this(Action.get, target);
  Selector.doSet(Name target) : this(Action.set, target);

  bool operator ==(other) {
    return other is Selector &&
        other.action == this.action &&
        other.target == this.target;
  }

  int get hashCode => (action.index * 31) ^ target.hashCode;

  @override
  String toString() {
    switch (action) {
      case Action.get:
        return 'get:${target}';
      case Action.set:
        return 'set:${target}';
      case Action.invoke:
        return '${target}';
    }
  }
}

// TODO(kustermann): Try to extend the idea of tracking uses based on the 'this'
// hierarchy.
class NoDynamicUsesAnnotator {
  final DynamicSelectorsCollector _selectors;
  final ProcedureAttributesMetadataRepository _metadata;

  NoDynamicUsesAnnotator(Component component)
      : _selectors = DynamicSelectorsCollector.collect(component),
        _metadata = new ProcedureAttributesMetadataRepository() {
    component.addMetadataRepository(_metadata);
  }

  visitComponent(Component component) {
    for (var library in component.libraries) {
      for (var klass in library.classes) {
        visitClass(klass);
      }
    }
  }

  visitClass(Class node) {
    for (var member in node.members) {
      if (member is Procedure) {
        visitProcedure(member);
      } else if (member is Field) {
        visitField(member);
      }
    }
  }

  visitField(Field node) {
    if (node.isStatic || node.name.text == 'call') {
      return;
    }

    final selector = new Selector.doSet(node.name);
    if (_selectors.dynamicSelectors.contains(selector)) {
      return;
    }

    ProcedureAttributesMetadata metadata;
    if (!_selectors.nonThisSelectors.contains(selector)) {
      metadata = const ProcedureAttributesMetadata(
          methodOrSetterCalledDynamically: false,
          getterCalledDynamically: false,
          hasNonThisUses: true,
          hasTearOffUses: false);
    } else {
      metadata = const ProcedureAttributesMetadata.noDynamicUses();
    }
    _metadata.mapping[node] = metadata;
  }

  visitProcedure(Procedure node) {
    if (node.isStatic || node.name.text == 'call') {
      return;
    }

    Selector selector;
    if (node.kind == ProcedureKind.Method) {
      selector = new Selector.doInvoke(node.name);
    } else if (node.kind == ProcedureKind.Setter) {
      selector = new Selector.doSet(node.name);
    } else {
      return;
    }

    if (_selectors.dynamicSelectors.contains(selector)) {
      return;
    }

    final bool hasNonThisUses = _selectors.nonThisSelectors.contains(selector);
    final bool hasTearOffUses = _selectors.tearOffSelectors.contains(selector);
    ProcedureAttributesMetadata metadata;
    if (!hasNonThisUses && !hasTearOffUses) {
      metadata = const ProcedureAttributesMetadata(
          methodOrSetterCalledDynamically: false,
          getterCalledDynamically: false,
          hasNonThisUses: false,
          hasTearOffUses: false);
    } else if (!hasNonThisUses && hasTearOffUses) {
      metadata = const ProcedureAttributesMetadata(
          methodOrSetterCalledDynamically: false,
          getterCalledDynamically: false,
          hasNonThisUses: false,
          hasTearOffUses: true);
    } else if (hasNonThisUses && !hasTearOffUses) {
      metadata = const ProcedureAttributesMetadata(
          methodOrSetterCalledDynamically: false,
          getterCalledDynamically: false,
          hasNonThisUses: true,
          hasTearOffUses: false);
    } else {
      metadata = const ProcedureAttributesMetadata.noDynamicUses();
    }
    _metadata.mapping[node] = metadata;
  }
}

class DynamicSelectorsCollector extends RecursiveVisitor {
  final Set<Selector> dynamicSelectors = new Set<Selector>();
  final Set<Selector> nonThisSelectors = new Set<Selector>();
  final Set<Selector> tearOffSelectors = new Set<Selector>();

  static DynamicSelectorsCollector collect(Component component) {
    final v = new DynamicSelectorsCollector();
    v.visitComponent(component);

    // We only populate [nonThisSelectors] and [tearOffSelectors] inside the
    // non-dynamic case (for efficiency reasons) while visiting the [Component].
    //
    // After the recursive visit of [Component] we complete the sets here.
    for (final Selector selector in v.dynamicSelectors) {
      // All dynamic getters can be tearoffs.
      if (selector.action == Action.get) {
        v.tearOffSelectors.add(new Selector.doInvoke(selector.target));
      }

      // All dynamic selectors are non-this selectors.
      v.nonThisSelectors.add(selector);
    }

    return v;
  }

  @override
  visitInstanceInvocation(InstanceInvocation node) {
    super.visitInstanceInvocation(node);
    if (node.receiver is! ThisExpression) {
      nonThisSelectors.add(new Selector.doInvoke(node.name));
    }
  }

  @override
  visitDynamicInvocation(DynamicInvocation node) {
    super.visitDynamicInvocation(node);
    dynamicSelectors.add(new Selector.doInvoke(node.name));
  }

  @override
  visitEqualsCall(EqualsCall node) {
    super.visitEqualsCall(node);
    if (node.left is! ThisExpression) {
      nonThisSelectors.add(new Selector.doInvoke(Name('==')));
    }
  }

  @override
  visitInstanceGet(InstanceGet node) {
    super.visitInstanceGet(node);
    if (node.receiver is! ThisExpression) {
      nonThisSelectors.add(new Selector.doGet(node.name));
    }
  }

  @override
  visitDynamicGet(DynamicGet node) {
    super.visitDynamicGet(node);
    dynamicSelectors.add(new Selector.doGet(node.name));
  }

  @override
  visitInstanceTearOff(InstanceTearOff node) {
    super.visitInstanceTearOff(node);
    if (node.receiver is! ThisExpression) {
      nonThisSelectors.add(new Selector.doGet(node.name));
    }
    tearOffSelectors.add(new Selector.doInvoke(node.name));
  }

  @override
  visitInstanceSet(InstanceSet node) {
    super.visitInstanceSet(node);
    if (node.receiver is! ThisExpression) {
      nonThisSelectors.add(new Selector.doSet(node.name));
    }
  }

  @override
  visitDynamicSet(DynamicSet node) {
    super.visitDynamicSet(node);
    dynamicSelectors.add(new Selector.doSet(node.name));
  }
}
