// Copyright (c) 2014, 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 dart2js.resolution.registry;

import '../common.dart';
import '../common/backend_api.dart'
    show Backend, ForeignResolver, NativeRegistry;
import '../common/resolution.dart'
    show Feature, ListLiteralUse, MapLiteralUse, ResolutionImpact, Target;
import '../common/registry.dart' show Registry;
import '../compiler.dart' show Compiler;
import '../constants/expressions.dart';
import '../dart_types.dart';
import '../diagnostics/source_span.dart';
import '../enqueue.dart' show ResolutionEnqueuer;
import '../elements/elements.dart';
import '../tree/tree.dart';
import '../util/util.dart' show Setlet;
import '../universe/call_structure.dart' show CallStructure;
import '../universe/selector.dart' show Selector;
import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
import '../universe/world_impact.dart' show WorldImpact, WorldImpactBuilder;
import '../util/enumset.dart' show EnumSet;

import 'send_structure.dart';

import 'members.dart' show ResolverVisitor;
import 'tree_elements.dart' show TreeElementMapping;

class _ResolutionWorldImpact extends ResolutionImpact
    with WorldImpactBuilder
    implements NativeRegistry {
  final String name;
  EnumSet<Feature> _features;
  Setlet<MapLiteralUse> _mapLiterals;
  Setlet<ListLiteralUse> _listLiterals;
  Setlet<String> _constSymbolNames;
  Setlet<ConstantExpression> _constantLiterals;
  Setlet<dynamic> _nativeData;

  _ResolutionWorldImpact(this.name);

  void registerMapLiteral(MapLiteralUse mapLiteralUse) {
    assert(mapLiteralUse != null);
    if (_mapLiterals == null) {
      _mapLiterals = new Setlet<MapLiteralUse>();
    }
    _mapLiterals.add(mapLiteralUse);
  }

  @override
  Iterable<MapLiteralUse> get mapLiterals {
    return _mapLiterals != null ? _mapLiterals : const <MapLiteralUse>[];
  }

  void registerListLiteral(ListLiteralUse listLiteralUse) {
    assert(listLiteralUse != null);
    if (_listLiterals == null) {
      _listLiterals = new Setlet<ListLiteralUse>();
    }
    _listLiterals.add(listLiteralUse);
  }

  @override
  Iterable<ListLiteralUse> get listLiterals {
    return _listLiterals != null ? _listLiterals : const <ListLiteralUse>[];
  }

  void registerConstSymbolName(String name) {
    if (_constSymbolNames == null) {
      _constSymbolNames = new Setlet<String>();
    }
    _constSymbolNames.add(name);
  }

  @override
  Iterable<String> get constSymbolNames {
    return _constSymbolNames != null ? _constSymbolNames : const <String>[];
  }

  void registerFeature(Feature feature) {
    if (_features == null) {
      _features = new EnumSet<Feature>();
    }
    _features.add(feature);
  }

  @override
  Iterable<Feature> get features {
    return _features != null
        ? _features.iterable(Feature.values)
        : const <Feature>[];
  }

  void registerConstantLiteral(ConstantExpression constant) {
    if (_constantLiterals == null) {
      _constantLiterals = new Setlet<ConstantExpression>();
    }
    _constantLiterals.add(constant);
  }

  Iterable<ConstantExpression> get constantLiterals {
    return _constantLiterals != null
        ? _constantLiterals
        : const <ConstantExpression>[];
  }

  void registerNativeData(dynamic nativeData) {
    assert(nativeData != null);
    if (_nativeData == null) {
      _nativeData = new Setlet<dynamic>();
    }
    _nativeData.add(nativeData);
  }

  @override
  Iterable<dynamic> get nativeData {
    return _nativeData != null ? _nativeData : const <dynamic>[];
  }

  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.write('_ResolutionWorldImpact($name)');
    WorldImpact.printOn(sb, this);
    if (_features != null) {
      sb.write('\n features:');
      for (Feature feature in _features.iterable(Feature.values)) {
        sb.write('\n  $feature');
      }
    }
    if (_mapLiterals != null) {
      sb.write('\n map-literals:');
      for (MapLiteralUse use in _mapLiterals) {
        sb.write('\n  $use');
      }
    }
    if (_listLiterals != null) {
      sb.write('\n list-literals:');
      for (ListLiteralUse use in _listLiterals) {
        sb.write('\n  $use');
      }
    }
    if (_constantLiterals != null) {
      sb.write('\n const-literals:');
      for (ConstantExpression constant in _constantLiterals) {
        sb.write('\n  ${constant.toDartText()}');
      }
    }
    if (_constSymbolNames != null) {
      sb.write('\n const-symbol-names: $_constSymbolNames');
    }
    return sb.toString();
  }
}

/// [ResolutionRegistry] collects all resolution information. It stores node
/// related information in a [TreeElements] mapping and registers calls with
/// [Backend], [World] and [Enqueuer].
// TODO(johnniwinther): Split this into an interface and implementation class.
class ResolutionRegistry extends Registry {
  final Target target;
  final TreeElementMapping mapping;
  final _ResolutionWorldImpact worldImpact;

  ResolutionRegistry(this.target, TreeElementMapping mapping)
      : this.mapping = mapping,
        this.worldImpact =
            new _ResolutionWorldImpact(mapping.analyzedElement.toString());

  bool get isForResolution => true;

  String toString() => 'ResolutionRegistry for ${mapping.analyzedElement}';

  //////////////////////////////////////////////////////////////////////////////
  //  Node-to-Element mapping functionality.
  //////////////////////////////////////////////////////////////////////////////

  /// Register [node] as the declaration of [element].
  void defineFunction(FunctionExpression node, FunctionElement element) {
    // TODO(sigurdm): Remove when not needed by the dart2dart backend.
    if (node.name != null) {
      mapping[node.name] = element;
    }
    mapping[node] = element;
  }

  /// Register [node] as a reference to [element].
  Element useElement(Node node, Element element) {
    if (element == null) return null;
    return mapping[node] = element;
  }

  /// Register [node] as the declaration of [element].
  void defineElement(Node node, Element element) {
    mapping[node] = element;
  }

  /// Returns the [Element] defined by [node].
  Element getDefinition(Node node) {
    return mapping[node];
  }

  /// Sets the loop variable of the for-in [node] to be [element].
  void setForInVariable(ForIn node, Element element) {
    mapping[node] = element;
  }

  /// Sets the target constructor [node] to be [element].
  void setRedirectingTargetConstructor(
      RedirectingFactoryBody node, ConstructorElement element) {
    useElement(node, element);
  }

  //////////////////////////////////////////////////////////////////////////////
  //  Node-to-Selector mapping functionality.
  //////////////////////////////////////////////////////////////////////////////

  void setSelector(Node node, Selector selector) {
    mapping.setSelector(node, selector);
  }

  void setGetterSelectorInComplexSendSet(SendSet node, Selector selector) {
    mapping.setGetterSelectorInComplexSendSet(node, selector);
  }

  void setOperatorSelectorInComplexSendSet(SendSet node, Selector selector) {
    mapping.setOperatorSelectorInComplexSendSet(node, selector);
  }

  //////////////////////////////////////////////////////////////////////////////
  //  Node-to-Type mapping functionality.
  //////////////////////////////////////////////////////////////////////////////

  DartType useType(Node annotation, DartType type) {
    if (type != null) {
      mapping.setType(annotation, type);
    }
    return type;
  }

  void setType(Node node, DartType type) => mapping.setType(node, type);

  DartType getType(Node node) => mapping.getType(node);

  //////////////////////////////////////////////////////////////////////////////
  //  Node-to-Constant mapping functionality.
  //////////////////////////////////////////////////////////////////////////////

  ConstantExpression getConstant(Node node) => mapping.getConstant(node);

  void setConstant(Node node, ConstantExpression constant) {
    mapping.setConstant(node, constant);
  }

  //////////////////////////////////////////////////////////////////////////////
  //  Target/Label functionality.
  //////////////////////////////////////////////////////////////////////////////

  /// Register [node] to be the declaration of [label].
  void defineLabel(Label node, LabelDefinition label) {
    mapping.defineLabel(node, label);
  }

  /// Undefine the label of [node].
  /// This is used to cleanup and detect unused labels.
  void undefineLabel(Label node) {
    mapping.undefineLabel(node);
  }

  /// Register the target of [node] as reference to [label].
  void useLabel(GotoStatement node, LabelDefinition label) {
    mapping.registerTargetLabel(node, label);
  }

  /// Register [node] to be the declaration of [target].
  void defineTarget(Node node, JumpTarget target) {
    assert(invariant(node, node is Statement || node is SwitchCase,
        message: "Only statements and switch cases can define targets."));
    mapping.defineTarget(node, target);
  }

  /// Returns the [JumpTarget] defined by [node].
  JumpTarget getTargetDefinition(Node node) {
    assert(invariant(node, node is Statement || node is SwitchCase,
        message: "Only statements and switch cases can define targets."));
    return mapping.getTargetDefinition(node);
  }

  /// Undefine the target of [node]. This is used to cleanup unused targets.
  void undefineTarget(Node node) {
    assert(invariant(node, node is Statement || node is SwitchCase,
        message: "Only statements and switch cases can define targets."));
    mapping.undefineTarget(node);
  }

  /// Register the target of [node] to be [target].
  void registerTargetOf(GotoStatement node, JumpTarget target) {
    mapping.registerTargetOf(node, target);
  }

  //////////////////////////////////////////////////////////////////////////////
  //  Potential access registration.
  //////////////////////////////////////////////////////////////////////////////

  void setAccessedByClosureIn(
      Node contextNode, VariableElement element, Node accessNode) {
    mapping.setAccessedByClosureIn(contextNode, element, accessNode);
  }

  void registerPotentialMutation(VariableElement element, Node mutationNode) {
    mapping.registerPotentialMutation(element, mutationNode);
  }

  void registerPotentialMutationInClosure(
      VariableElement element, Node mutationNode) {
    mapping.registerPotentialMutationInClosure(element, mutationNode);
  }

  void registerPotentialMutationIn(
      Node contextNode, VariableElement element, Node mutationNode) {
    mapping.registerPotentialMutationIn(contextNode, element, mutationNode);
  }

  //////////////////////////////////////////////////////////////////////////////
  //  Various Backend/Enqueuer/World registration.
  //////////////////////////////////////////////////////////////////////////////

  void registerStaticUse(StaticUse staticUse) {
    worldImpact.registerStaticUse(staticUse);
  }

  /// Register the use of a type.
  void registerTypeUse(TypeUse typeUse) {
    worldImpact.registerTypeUse(typeUse);
  }

  void registerSuperUse(SourceSpan span) {
    mapping.addSuperUse(span);
  }

  void registerTypeLiteral(Send node, DartType type) {
    mapping.setType(node, type);
    worldImpact.registerTypeUse(new TypeUse.typeLiteral(type));
  }

  void registerLiteralList(Node node, InterfaceType type,
      {bool isConstant, bool isEmpty}) {
    setType(node, type);
    worldImpact.registerListLiteral(
        new ListLiteralUse(type, isConstant: isConstant, isEmpty: isEmpty));
  }

  void registerMapLiteral(Node node, InterfaceType type,
      {bool isConstant, bool isEmpty}) {
    setType(node, type);
    worldImpact.registerMapLiteral(
        new MapLiteralUse(type, isConstant: isConstant, isEmpty: isEmpty));
  }

  void registerForeignCall(Node node, Element element,
      CallStructure callStructure, ResolverVisitor visitor) {
    var nativeData = target.resolveForeignCall(node, element, callStructure,
        new ForeignResolutionResolver(visitor, this));
    if (nativeData != null) {
      // Split impact from resolution result.
      mapping.registerNativeData(node, nativeData);
      worldImpact.registerNativeData(nativeData);
    }
  }

  void registerDynamicUse(DynamicUse dynamicUse) {
    worldImpact.registerDynamicUse(dynamicUse);
  }

  void registerFeature(Feature feature) {
    worldImpact.registerFeature(feature);
  }

  void registerConstSymbol(String name) {
    worldImpact.registerConstSymbolName(name);
  }

  void registerConstantLiteral(ConstantExpression constant) {
    worldImpact.registerConstantLiteral(constant);
  }

  ClassElement defaultSuperclass(ClassElement element) {
    return target.defaultSuperclass(element);
  }

  void registerInstantiation(InterfaceType type) {
    worldImpact.registerTypeUse(new TypeUse.instantiation(type));
  }

  void registerSendStructure(Send node, SendStructure sendStructure) {
    mapping.setSendStructure(node, sendStructure);
  }

  void registerNewStructure(NewExpression node, NewStructure newStructure) {
    mapping.setNewStructure(node, newStructure);
  }

  // TODO(johnniwinther): Remove this when [SendStructure]s are part of the
  // [ResolutionResult].
  SendStructure getSendStructure(Send node) {
    return mapping.getSendStructure(node);
  }

  void registerTryStatement() {
    mapping.containsTryStatement = true;
  }
}

class ForeignResolutionResolver implements ForeignResolver {
  final ResolverVisitor visitor;
  final ResolutionRegistry registry;

  ForeignResolutionResolver(this.visitor, this.registry);

  @override
  ConstantExpression getConstant(Node node) {
    return registry.getConstant(node);
  }

  @override
  void registerInstantiatedType(InterfaceType type) {
    registry.registerInstantiation(type);
  }

  @override
  DartType resolveTypeFromString(Node node, String typeName) {
    return visitor.resolveTypeFromString(node, typeName);
  }
}
