// 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 'package:compiler/src/ssa/metrics.dart';

import '../common.dart';
import '../common/codegen.dart' show CodegenResult, CodegenRegistry;
import '../common/elements.dart' show CommonElements, JElementEnvironment;
import '../common/metrics.dart';
import '../common/tasks.dart' show CompilerTask, Measurer;
import '../elements/entities.dart';
import '../elements/types.dart';
import '../inferrer/types.dart';
import '../io/source_information.dart';
import '../js/js.dart' as js;
import '../js/rewrite_async.dart';
import '../js_backend/backend.dart' show FunctionCompiler;
import '../js_backend/codegen_inputs.dart' show CodegenInputs;
import '../js_backend/namer.dart' show ModularNamer;
import '../js_backend/namer.dart' show ModularNamerImpl;
import '../js_backend/type_reference.dart' show TypeReference;
import '../js_emitter/code_emitter_task.dart' show ModularEmitter;
import '../js_emitter/startup_emitter/emitter.dart' show ModularEmitterImpl;
import '../js_model/elements.dart';
import '../js_model/type_recipe.dart' show TypeExpressionRecipe;
import '../js_model/js_strategy.dart';
import '../js_model/js_world.dart' show JClosedWorld;
import '../options.dart';
import '../universe/call_structure.dart' show CallStructure;
import '../universe/use.dart' show StaticUse;

import 'codegen.dart';
import 'nodes.dart';
import 'optimize.dart';

class SsaFunctionCompiler implements FunctionCompiler {
  final CompilerOptions _options;
  final DiagnosticReporter _reporter;
  final SsaMetrics _metrics;
  final SsaCodeGeneratorTask generator;
  final SsaBuilderTask _builder;
  final SsaOptimizerTask optimizer;
  final SourceInformationStrategy sourceInformationStrategy;
  late final GlobalTypeInferenceResults _globalInferenceResults;
  late final GlobalTypeInferenceResults _trivialInferenceResults;
  late final CodegenInputs _codegen;

  SsaFunctionCompiler(
    this._options,
    this._reporter,
    this._metrics,
    JsBackendStrategy backendStrategy,
    Measurer measurer,
    this.sourceInformationStrategy,
  ) : generator = SsaCodeGeneratorTask(
        measurer,
        _options,
        sourceInformationStrategy,
      ),
      _builder = SsaBuilderTask(
        measurer,
        backendStrategy,
        sourceInformationStrategy,
        _metrics,
      ),
      optimizer = SsaOptimizerTask(measurer, _options);

  @override
  void initialize(
    GlobalTypeInferenceResults globalInferenceResults,
    CodegenInputs codegen,
  ) {
    _globalInferenceResults = globalInferenceResults;
    _trivialInferenceResults = TrivialGlobalTypeInferenceResults(
      globalInferenceResults.closedWorld,
      _globalInferenceResults.globalLocalsMap,
    );
    _codegen = codegen;
    _builder.onCodegenStart(globalInferenceResults.closedWorld);
  }

  /// Generates JavaScript code for [member].
  /// Using the ssa builder, optimizer and code generator.
  @override
  CodegenResult compile(MemberEntity member) {
    // We don't have inference data for stubs. We could use some inferred types
    // for the target function but stubs are so simple that this usually doesn't
    // produce better code. Deserializing inference results is also expensive so
    // we avoid it here.
    final inferenceResults = member is JParameterStub
        ? _trivialInferenceResults
        : _globalInferenceResults;
    JClosedWorld closedWorld = _globalInferenceResults.closedWorld;

    CodegenRegistry registry = CodegenRegistry(
      closedWorld.elementEnvironment,
      member,
    );
    ModularNamer namer = ModularNamerImpl(
      registry,
      closedWorld.commonElements,
      _codegen.fixedNames,
    );
    ModularEmitter emitter = ModularEmitterImpl(namer, registry, _options);
    if (member is ConstructorEntity &&
        member.enclosingClass == closedWorld.commonElements.jsNullClass) {
      // Work around a problem compiling JSNull's constructor.
      return registry.close(null);
    }

    final graph = _builder.build(
      member,
      inferenceResults,
      _codegen,
      registry,
      namer,
      emitter,
    );
    if (graph == null) {
      return registry.close(null);
    }

    optimizer.optimize(
      member,
      graph,
      _codegen,
      closedWorld,
      inferenceResults,
      registry,
      _metrics,
    );
    js.Expression result = generator.generateCode(
      member,
      graph,
      _codegen,
      closedWorld,
      registry,
      namer,
      emitter,
    );
    if (graph.needsAsyncRewrite) {
      SourceInformationBuilder sourceInformationBuilder =
          sourceInformationStrategy.createBuilderForContext(member);
      result = _rewriteAsync(
        _codegen,
        closedWorld.commonElements,
        closedWorld.elementEnvironment,
        registry,
        namer,
        emitter,
        member as FunctionEntity,
        result,
        graph.asyncElementType,
        sourceInformationBuilder.buildAsyncBody(),
        sourceInformationBuilder.buildAsyncExit(),
      );
      _codegen.tracer.traceJavaScriptText(
        'JavaScript.rewrite',
        result.debugPrint,
      );
    }
    if (result.sourceInformation == null) {
      result = result.withSourceInformation(
        sourceInformationStrategy.buildSourceMappedMarker(),
      );
    }

    return registry.close(result as js.Fun);
  }

  js.Expression _rewriteAsync(
    CodegenInputs codegen,
    CommonElements commonElements,
    JElementEnvironment elementEnvironment,
    CodegenRegistry registry,
    ModularNamer namer,
    ModularEmitter emitter,
    FunctionEntity element,
    js.Expression code,
    DartType? asyncTypeParameter,
    SourceInformation? bodySourceInformation,
    SourceInformation? exitSourceInformation,
  ) {
    if (element.asyncMarker == AsyncMarker.sync) return code;

    late final AsyncRewriterBase rewriter;
    js.Name name = namer.methodPropertyName(
      element is JGeneratorBody ? element.function : element,
    );

    switch (element.asyncMarker) {
      case AsyncMarker.async:
        rewriter = _makeAsyncRewriter(
          codegen,
          commonElements,
          elementEnvironment,
          registry,
          namer,
          emitter,
          element,
          code,
          asyncTypeParameter,
          name,
        );
        break;
      case AsyncMarker.syncStar:
        rewriter = _makeSyncStarRewriter(
          codegen,
          commonElements,
          elementEnvironment,
          registry,
          namer,
          emitter,
          element,
          code,
          asyncTypeParameter,
          name,
        );
        break;
      case AsyncMarker.asyncStar:
        rewriter = _makeAsyncStarRewriter(
          codegen,
          commonElements,
          elementEnvironment,
          registry,
          namer,
          emitter,
          element,
          code,
          asyncTypeParameter,
          name,
        );
        break;
      case AsyncMarker.sync:
        throw StateError('Cannot rewrite sync method as async.');
    }
    return rewriter.rewrite(
      code as js.Fun,
      bodySourceInformation,
      exitSourceInformation,
    );
  }

  /// Returns an optional expression that evaluates [type].  Returns `null` if
  /// the type expression is determined by the outside context and should be
  /// added as a function parameter to the rewritten code.
  // TODO(sra): We could also return an empty list if the generator takes no
  // type (e.g. due to rtiNeed optimization).
  List<js.Expression>? _fetchItemType(
    CommonElements commonElements,
    CodegenRegistry registry,
    DartType? type,
  ) {
    if (type == null) return null;
    registry.registerStaticUse(
      StaticUse.staticInvoke(commonElements.findType, CallStructure.oneArg),
    );
    return [TypeReference(TypeExpressionRecipe(type))];
  }

  AsyncRewriter _makeAsyncRewriter(
    CodegenInputs codegen,
    CommonElements commonElements,
    JElementEnvironment elementEnvironment,
    CodegenRegistry registry,
    ModularNamer namer,
    ModularEmitter emitter,
    FunctionEntity element,
    js.Expression code,
    DartType? elementType,
    js.Name name,
  ) {
    FunctionEntity startFunction = commonElements.asyncHelperStartSync;
    FunctionEntity completerFactory = commonElements.asyncAwaitCompleterFactory;

    final itemTypeExpression = _fetchItemType(
      commonElements,
      registry,
      elementType,
    );

    AsyncRewriter rewriter = AsyncRewriter(
      _reporter,
      element,
      asyncStart: emitter.staticFunctionAccess(startFunction),
      asyncAwait: emitter.staticFunctionAccess(commonElements.asyncHelperAwait),
      asyncReturn: emitter.staticFunctionAccess(
        commonElements.asyncHelperReturn,
      ),
      asyncRethrow: emitter.staticFunctionAccess(
        commonElements.asyncHelperRethrow,
      ),
      wrapBody: emitter.staticFunctionAccess(commonElements.wrapBody),
      completerFactory: emitter.staticFunctionAccess(completerFactory),
      completerFactoryTypeArguments: itemTypeExpression,
      safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
      bodyName: namer.deriveAsyncBodyName(name),
    );

    registry.registerStaticUse(
      StaticUse.staticInvoke(completerFactory, CallStructure.unnamed(0, 1), [
        elementEnvironment.getFunctionAsyncOrSyncStarElementType(element),
      ]),
    );

    return rewriter;
  }

  SyncStarRewriter _makeSyncStarRewriter(
    CodegenInputs codegen,
    CommonElements commonElements,
    JElementEnvironment elementEnvironment,
    CodegenRegistry registry,
    ModularNamer namer,
    ModularEmitter emitter,
    FunctionEntity element,
    js.Expression code,
    DartType? asyncTypeParameter,
    js.Name name,
  ) {
    SyncStarRewriter rewriter = SyncStarRewriter(
      _reporter,
      element,
      iteratorCurrentValueProperty: namer.instanceFieldPropertyName(
        commonElements.syncStarIteratorCurrentField,
      ),
      iteratorDatumProperty: namer.instanceFieldPropertyName(
        commonElements.syncStarIteratorDatumField,
      ),
      yieldStarSelector: namer.instanceMethodName(
        commonElements.syncStarIteratorYieldStarMethod,
      ),
      safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
      bodyName: namer.deriveAsyncBodyName(name),
    );

    return rewriter;
  }

  AsyncStarRewriter _makeAsyncStarRewriter(
    CodegenInputs codegen,
    CommonElements commonElements,
    JElementEnvironment elementEnvironment,
    CodegenRegistry registry,
    ModularNamer namer,
    ModularEmitter emitter,
    FunctionEntity element,
    js.Expression code,
    DartType? asyncTypeParameter,
    js.Name name,
  ) {
    final itemTypeExpression = _fetchItemType(
      commonElements,
      registry,
      asyncTypeParameter,
    );

    AsyncStarRewriter rewriter = AsyncStarRewriter(
      _reporter,
      element,
      asyncStarHelper: emitter.staticFunctionAccess(
        commonElements.asyncStarHelper,
      ),
      streamOfController: emitter.staticFunctionAccess(
        commonElements.streamOfController,
      ),
      wrapBody: emitter.staticFunctionAccess(commonElements.wrapBody),
      newController: emitter.staticFunctionAccess(
        commonElements.asyncStarStreamControllerFactory,
      ),
      newControllerTypeArguments: itemTypeExpression,
      safeVariableName: namer.safeVariablePrefixForAsyncRewrite,
      yieldExpression: emitter.staticFunctionAccess(commonElements.yieldSingle),
      yieldStarExpression: emitter.staticFunctionAccess(
        commonElements.yieldStar,
      ),
      bodyName: namer.deriveAsyncBodyName(name),
    );

    registry.registerStaticUse(
      StaticUse.staticInvoke(
        commonElements.asyncStarStreamControllerFactory,
        CallStructure.unnamed(1, 1),
        [elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)],
      ),
    );

    return rewriter;
  }

  @override
  List<CompilerTask> get tasks {
    return [_builder, optimizer, generator];
  }
}

abstract class SsaBuilder {
  /// Creates the [HGraph] for [member] or returns `null` if no code is needed
  /// for [member].
  HGraph? build(
    MemberEntity member,
    GlobalTypeInferenceResults globalInferenceResults,
    CodegenInputs codegen,
    CodegenRegistry registry,
    ModularNamer namer,
    ModularEmitter emitter,
  );
}

class SsaBuilderTask extends CompilerTask {
  final JsBackendStrategy _backendStrategy;
  final SourceInformationStrategy _sourceInformationFactory;
  late SsaBuilder _builder;

  final SsaMetrics _ssaMetrics;

  @override
  Metrics metrics = Metrics.none();

  SsaBuilderTask(
    super.measurer,
    this._backendStrategy,
    this._sourceInformationFactory,
    this._ssaMetrics,
  );

  @override
  String get name => 'SSA builder';

  void onCodegenStart(JClosedWorld closedWorld) {
    _builder = _backendStrategy.createSsaBuilder(
      this,
      closedWorld,
      _sourceInformationFactory,
    );
    metrics = _ssaMetrics;
  }

  /// Creates the [HGraph] for [member] or returns `null` if no code is needed
  /// for [member].
  HGraph? build(
    MemberEntity member,
    GlobalTypeInferenceResults globalInferenceResults,
    CodegenInputs codegen,
    CodegenRegistry registry,
    ModularNamer namer,
    ModularEmitter emitter,
  ) {
    return _builder.build(
      member,
      globalInferenceResults,
      codegen,
      registry,
      namer,
      emitter,
    );
  }
}
