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

part of js_backend;

class NativeEmitter {

  CodeEmitterTask emitter;
  CodeBuffer nativeBuffer;

  // Native classes found in the application.
  Set<ClassElement> nativeClasses = new Set<ClassElement>();

  // Caches the native subtypes of a native class.
  Map<ClassElement, List<ClassElement>> subtypes;

  // Caches the direct native subtypes of a native class.
  Map<ClassElement, List<ClassElement>> directSubtypes;

  // Caches the methods that have a native body.
  Set<FunctionElement> nativeMethods;

  // Do we need the native emitter to take care of handling
  // noSuchMethod for us? This flag is set to true in the emitter if
  // it finds any native class that needs noSuchMethod handling.
  bool handleNoSuchMethod = false;

  NativeEmitter(this.emitter)
      : subtypes = new Map<ClassElement, List<ClassElement>>(),
        directSubtypes = new Map<ClassElement, List<ClassElement>>(),
        nativeMethods = new Set<FunctionElement>(),
        nativeBuffer = new CodeBuffer();

  Compiler get compiler => emitter.compiler;
  JavaScriptBackend get backend => compiler.backend;

  String get _ => emitter.space;
  String get n => emitter.n;
  String get N => emitter.N;

  String get dynamicName {
    Element element = compiler.findHelper('dynamicFunction');
    return backend.namer.isolateAccess(element);
  }

  String get dynamicFunctionTableName {
    Element element = compiler.findHelper('dynamicFunctionTable');
    return backend.namer.isolateAccess(element);
  }

  String get typeNameOfName {
    Element element = compiler.findHelper('getTypeNameOf');
    return backend.namer.isolateAccess(element);
  }

  String get defPropName {
    Element element = compiler.findHelper('defineProperty');
    return backend.namer.isolateAccess(element);
  }

  String get toStringHelperName {
    Element element = compiler.findHelper('toStringForNativeObject');
    return backend.namer.isolateAccess(element);
  }

  String get hashCodeHelperName {
    Element element = compiler.findHelper('hashCodeForNativeObject');
    return backend.namer.isolateAccess(element);
  }

  String get dispatchPropertyNameVariable {
    Element element = compiler.findInterceptor('dispatchPropertyName');
    return backend.namer.isolateAccess(element);
  }

  // The tags string contains comma-separated 'words' which are either dispatch
  // tags (having JavaScript identifier syntax) and directives that begin with
  // `!`.
  List<String> nativeTagsOfClassRaw(ClassElement cls) {
    String quotedName = cls.nativeTagInfo;
    return quotedName.substring(1, quotedName.length - 1).split(',');
  }

  List<String> nativeTagsOfClass(ClassElement cls) {
    return nativeTagsOfClassRaw(cls).where((s) => !s.startsWith('!')).toList();
  }

  bool nativeHasTagsMarker(ClassElement cls, String marker) {
    return nativeTagsOfClassRaw(cls).contains(marker);
  }

  bool nativeForcedNonLeaf(ClassElement cls) =>
      nativeHasTagsMarker(cls, '!nonleaf');

  /**
   * Writes the class definitions for the interceptors to [mainBuffer].
   * Writes code to associate dispatch tags with interceptors to [nativeBuffer].
   *
   * The interceptors are filtered to avoid emitting trivial interceptors.  For
   * example, if the program contains no code that can distinguish between the
   * numerous subclasses of `Element` then we can pretend that `Element` is a
   * leaf class, and all instances of subclasses of `Element` are instances of
   * `Element`.
   *
   * There is also a performance benefit (in addition to the obvious code size
   * benefit), due to how [getNativeInterceptor] works.  Finding the interceptor
   * of a leaf class in the hierarchy is more efficient that a non-leaf, so it
   * improves performance when more classes can be treated as leaves.
   *
   * [classes] contains native classes, mixin applications, and user subclasses
   * of native classes.  ONLY the native classes are generated here.  [classes]
   * is sorted in desired output order.
   *
   * [additionalProperties] is used to collect properties that are pushed up
   * from the above optimizations onto a non-native class, e.g, `Interceptor`.
   */
  void generateNativeClasses(
      List<ClassElement> classes,
      CodeBuffer mainBuffer,
      Map<ClassElement, Map<String, jsAst.Expression>> additionalProperties) {
    // Compute a pre-order traversal of the subclass forest.  We actually want a
    // post-order traversal but it is easier to compute the pre-order and use it
    // in reverse.

    List<ClassElement> preOrder = <ClassElement>[];
    Set<ClassElement> seen = new Set<ClassElement>();
    seen..add(compiler.objectClass)
        ..add(backend.jsInterceptorClass);
    void walk(ClassElement element) {
      if (seen.contains(element)) return;
      seen.add(element);
      walk(element.superclass);
      preOrder.add(element);
    }
    classes.forEach(walk);

    // Generate code for each native class into [ClassBuilder]s.

    Map<ClassElement, ClassBuilder> builders =
        new Map<ClassElement, ClassBuilder>();
    for (ClassElement classElement in classes) {
      if (classElement.isNative()) {
        ClassBuilder builder = generateNativeClass(classElement);
        builders[classElement] = builder;
      }
    }

    // Find which classes are needed and which are non-leaf classes.  Any class
    // that is not needed can be treated as a leaf class equivalent to some
    // needed class.

    Set<ClassElement> neededClasses = new Set<ClassElement>();
    Set<ClassElement> nonleafClasses = new Set<ClassElement>();

    Map<ClassElement, List<ClassElement>> extensionPoints =
        computeExtensionPoints(preOrder);

    neededClasses.add(compiler.objectClass);

    Set<ClassElement> neededByConstant =
        emitter.interceptorEmitter.interceptorsReferencedFromConstants();
    Set<ClassElement> modifiedClasses =
        emitter.typeTestEmitter.classesModifiedByEmitRuntimeTypeSupport();

    for (ClassElement classElement in preOrder.reversed) {
      // Post-order traversal ensures we visit the subclasses before their
      // superclass.  This makes it easy to tell if a class is needed because a
      // subclass is needed.
      ClassBuilder builder = builders[classElement];
      bool needed = false;
      if (builder == null) {
        // Mixin applications (native+mixin) are non-native, so [classElement]
        // has already been emitted as a regular class.  Mark [classElement] as
        // 'needed' to ensure the native superclass is needed.
        needed = true;
      } else if (!builder.isTrivial) {
        needed = true;
      } else if (neededByConstant.contains(classElement)) {
        needed = true;
      } else if (modifiedClasses.contains(classElement)) {
        // TODO(9556): Remove this test when [emitRuntimeTypeSupport] no longer
        // adds information to a class prototype or constructor.
        needed = true;
      } else if (extensionPoints.containsKey(classElement)) {
        needed = true;
      }
      if (classElement.isNative() && nativeForcedNonLeaf(classElement)) {
        needed = true;
        nonleafClasses.add(classElement);
      }

      if (needed || neededClasses.contains(classElement)) {
        neededClasses.add(classElement);
        neededClasses.add(classElement.superclass);
        nonleafClasses.add(classElement.superclass);
      }
    }

    // Collect all the tags that map to each native class.

    Map<ClassElement, Set<String>> leafTags =
        new Map<ClassElement, Set<String>>();
    Map<ClassElement, Set<String>> nonleafTags =
        new Map<ClassElement, Set<String>>();

    for (ClassElement classElement in classes) {
      if (!classElement.isNative()) continue;
      List<String> nativeTags = nativeTagsOfClass(classElement);

      if (nonleafClasses.contains(classElement) ||
          extensionPoints.containsKey(classElement)) {
        nonleafTags
            .putIfAbsent(classElement, () => new Set<String>())
            .addAll(nativeTags);
      } else {
        ClassElement sufficingInterceptor = classElement;
        while (!neededClasses.contains(sufficingInterceptor)) {
          sufficingInterceptor = sufficingInterceptor.superclass;
        }
        if (sufficingInterceptor == compiler.objectClass) {
          sufficingInterceptor = backend.jsInterceptorClass;
        }
        leafTags
            .putIfAbsent(sufficingInterceptor, () => new Set<String>())
            .addAll(nativeTags);
      }
    }

    // Add properties containing the information needed to construct maps used
    // by getNativeInterceptor and custom elements.
    if (compiler.enqueuer.codegen.nativeEnqueuer
        .hasInstantiatedNativeClasses()) {
      void generateClassInfo(ClassElement classElement) {
        // Property has the form:
        //
        //    "%": "leafTag1|leafTag2|...;nonleafTag1|...;Class1|Class2|...",
        //
        // If there is no data following a semicolon, the semicolon can be
        // omitted.

        String formatTags(Iterable<String> tags) {
          if (tags == null) return '';
          return (tags.toList()..sort()).join('|');
        }

        List<ClassElement> extensions = extensionPoints[classElement];

        String leafStr = formatTags(leafTags[classElement]);
        String nonleafStr = formatTags(nonleafTags[classElement]);

        StringBuffer sb = new StringBuffer(leafStr);
        if (nonleafStr != '') {
          sb..write(';')..write(nonleafStr);
        }
        if (extensions != null) {
          sb..write(';')
            ..writeAll(extensions.map(backend.namer.getNameOfClass), '|');
        }
        String encoding = sb.toString();

        ClassBuilder builder = builders[classElement];
        if (builder == null) {
          // No builder because this is an intermediate mixin application or
          // Interceptor - these are not direct native classes.
          if (encoding != '') {
            Map<String, jsAst.Expression> properties =
                additionalProperties.putIfAbsent(classElement,
                    () => new LinkedHashMap<String, jsAst.Expression>());
            properties[backend.namer.nativeSpecProperty] = js.string(encoding);
          }
        } else {
          builder.addProperty(
              backend.namer.nativeSpecProperty, js.string(encoding));
        }
      }
      generateClassInfo(backend.jsInterceptorClass);
      for (ClassElement classElement in classes) {
        generateClassInfo(classElement);
      }
    }

    // Emit the native class interceptors that were actually used.
    for (ClassElement classElement in classes) {
      if (!classElement.isNative()) continue;
      if (neededClasses.contains(classElement)) {
        // Define interceptor class for [classElement].
        emitter.classEmitter.emitClassBuilderWithReflectionData(
            backend.namer.getNameOfClass(classElement),
            classElement, builders[classElement],
            emitter.getElementDecriptor(classElement));
        emitter.needsDefineClass = true;
      }
    }
  }

  /**
   * Computes the native classes that are extended (subclassed) by non-native
   * classes and the set non-mative classes that extend them.  (A List is used
   * instead of a Set for out stability).
   */
  Map<ClassElement, List<ClassElement>> computeExtensionPoints(
      List<ClassElement> classes) {
    ClassElement nativeSuperclassOf(ClassElement element) {
      if (element == null) return null;
      if (element.isNative()) return element;
      return nativeSuperclassOf(element.superclass);
    }

    ClassElement nativeAncestorOf(ClassElement element) {
      return nativeSuperclassOf(element.superclass);
    }

    Map<ClassElement, List<ClassElement>> map =
        new Map<ClassElement, List<ClassElement>>();

    for (ClassElement classElement in classes) {
      if (classElement.isNative()) continue;
      ClassElement nativeAncestor = nativeAncestorOf(classElement);
      if (nativeAncestor != null) {
        map
          .putIfAbsent(nativeAncestor, () => <ClassElement>[])
          .add(classElement);
      }
    }
    return map;
  }

  ClassBuilder generateNativeClass(ClassElement classElement) {
    // TODO(sra): Issue #13731- this is commented out as part of custom element
    // constructor work.
    //assert(!classElement.hasBackendMembers);
    nativeClasses.add(classElement);

    ClassElement superclass = classElement.superclass;
    assert(superclass != null);
    // Fix superclass.  TODO(sra): make native classes inherit from Interceptor.
    assert(superclass != compiler.objectClass);
    if (superclass == compiler.objectClass) {
      superclass = backend.jsInterceptorClass;
    }

    String superName = backend.namer.getNameOfClass(superclass);

    ClassBuilder builder = new ClassBuilder(backend.namer);
    emitter.classEmitter.emitClassConstructor(classElement, builder, null);
    bool hasFields = emitter.classEmitter.emitFields(
        classElement, builder, superName, classIsNative: true);
    int propertyCount = builder.properties.length;
    emitter.classEmitter.emitClassGettersSetters(classElement, builder);
    emitter.classEmitter.emitInstanceMembers(classElement, builder);
    emitter.typeTestEmitter.emitIsTests(classElement, builder);

    if (!hasFields &&
        builder.properties.length == propertyCount &&
        superclass is! MixinApplicationElement) {
      builder.isTrivial = true;
    }

    return builder;
  }

  void finishGenerateNativeClasses() {
    // TODO(sra): Put specialized version of getNativeMethods on
    // `Object.prototype` to avoid checking in `getInterceptor` and
    // specializations.
  }

  void potentiallyConvertDartClosuresToJs(
      List<jsAst.Statement> statements,
      FunctionElement member,
      List<jsAst.Parameter> stubParameters) {
    FunctionSignature parameters = member.functionSignature;
    Element converter =
        compiler.findHelper('convertDartClosureToJS');
    String closureConverter = backend.namer.isolateAccess(converter);
    Set<String> stubParameterNames = new Set<String>.from(
        stubParameters.map((param) => param.name));
    parameters.forEachParameter((ParameterElement parameter) {
      String name = parameter.name;
      // If [name] is not in [stubParameters], then the parameter is an optional
      // parameter that was not provided for this stub.
      for (jsAst.Parameter stubParameter in stubParameters) {
        if (stubParameter.name == name) {
          DartType type = parameter.type.unalias(compiler);
          if (type is FunctionType) {
            // The parameter type is a function type either directly or through
            // typedef(s).
            FunctionType functionType = type;
            int arity = functionType.computeArity();
            statements.add(
                js('$name = $closureConverter($name, $arity)').toStatement());
            break;
          }
        }
      }
    });
  }

  List<jsAst.Statement> generateParameterStubStatements(
      Element member,
      bool isInterceptedMethod,
      String invocationName,
      List<jsAst.Parameter> stubParameters,
      List<jsAst.Expression> argumentsBuffer,
      int indexOfLastOptionalArgumentInParameters) {
    // The target JS function may check arguments.length so we need to
    // make sure not to pass any unspecified optional arguments to it.
    // For example, for the following Dart method:
    //   foo([x, y, z]);
    // The call:
    //   foo(y: 1)
    // must be turned into a JS call to:
    //   foo(null, y).

    ClassElement classElement = member.enclosingElement;

    List<jsAst.Statement> statements = <jsAst.Statement>[];
    potentiallyConvertDartClosuresToJs(statements, member, stubParameters);

    String target;
    jsAst.Expression receiver;
    List<jsAst.Expression> arguments;

    assert(invariant(member, nativeMethods.contains(member)));
    // When calling a JS method, we call it with the native name, and only the
    // arguments up until the last one provided.
    target = member.fixedBackendName();

    if (isInterceptedMethod) {
      receiver = argumentsBuffer[0];
      arguments = argumentsBuffer.sublist(1,
          indexOfLastOptionalArgumentInParameters + 1);
    } else {
      receiver = js('this');
      arguments = argumentsBuffer.sublist(0,
          indexOfLastOptionalArgumentInParameters + 1);
    }
    statements.add(new jsAst.Return(receiver[target](arguments)));

    return statements;
  }

  bool isSupertypeOfNativeClass(Element element) {
    if (element.isTypeVariable()) {
      compiler.internalError(element, "Is check for type variable.");
      return false;
    }
    if (element.computeType(compiler).unalias(compiler) is FunctionType) {
      // The element type is a function type either directly or through
      // typedef(s).
      return false;
    }

    if (!element.isClass()) {
      compiler.internalError(element, "Is check does not handle element.");
      return false;
    }

    if (backend.classesMixedIntoInterceptedClasses.contains(element)) {
      return true;
    }

    return subtypes[element] != null;
  }

  bool requiresNativeIsCheck(Element element) {
    // TODO(sra): Remove this function.  It determines if a native type may
    // satisfy a check against [element], in which case an interceptor must be
    // used.  We should also use an interceptor if the check can't be satisfied
    // by a native class in case we get a native instance that tries to spoof
    // the type info.  i.e the criteria for whether or not to use an interceptor
    // is whether the receiver can be native, not the type of the test.
    if (!element.isClass()) return false;
    ClassElement cls = element;
    if (Elements.isNativeOrExtendsNative(cls)) return true;
    return isSupertypeOfNativeClass(element);
  }

  void assembleCode(CodeBuffer targetBuffer) {
    List<jsAst.Property> objectProperties = <jsAst.Property>[];

    void addProperty(String name, jsAst.Expression value) {
      objectProperties.add(new jsAst.Property(js.string(name), value));
    }

    if (!nativeClasses.isEmpty) {
      // If the native emitter has been asked to take care of the
      // noSuchMethod handlers, we do that now.
      if (handleNoSuchMethod) {
        emitter.nsmEmitter.emitNoSuchMethodHandlers(addProperty);
      }
    }

    // If we have any properties to add to Object.prototype, we run
    // through them and add them using defineProperty.
    if (!objectProperties.isEmpty) {
      jsAst.Expression init =
          js.fun(['table'],
              new jsAst.ForIn(
                  new jsAst.VariableDeclarationList(
                      [new jsAst.VariableInitialization(
                          new jsAst.VariableDeclaration('key'),
                          null)]),
                  js('table'),
                  new jsAst.ExpressionStatement(
                      js('$defPropName(Object.prototype, key, table[key])'))))(
              new jsAst.ObjectInitializer(objectProperties));

      if (emitter.compiler.enableMinification) targetBuffer.add(';');
      targetBuffer.add(jsAst.prettyPrint(
          new jsAst.ExpressionStatement(init), compiler));
      targetBuffer.add('\n');
    }

    targetBuffer.add(nativeBuffer);
    targetBuffer.add('\n');
  }
}
