// 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 ssa;

import '../common/codegen.dart' show CodegenWorkItem, CodegenRegistry;
import '../common/tasks.dart' show CompilerTask, Measurer;
import '../constants/values.dart';
import '../elements/elements.dart' show MethodElement;
import '../elements/entities.dart' show FieldEntity, MemberEntity;
import '../io/source_information.dart';
import '../js/js.dart' as js;
import '../js_backend/backend.dart' show JavaScriptBackend, FunctionCompiler;
import '../universe/call_structure.dart';
import '../universe/use.dart';
import '../world.dart' show ClosedWorld;

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

class SsaFunctionCompiler implements FunctionCompiler {
  final SsaCodeGeneratorTask generator;
  final SsaBuilderTask _builder;
  final SsaOptimizerTask optimizer;
  final JavaScriptBackend backend;

  SsaFunctionCompiler(JavaScriptBackend backend, Measurer measurer,
      SourceInformationStrategy sourceInformationFactory)
      : generator = new SsaCodeGeneratorTask(backend, sourceInformationFactory),
        _builder = new SsaBuilderTask(backend, sourceInformationFactory),
        optimizer = new SsaOptimizerTask(backend),
        backend = backend;

  void onCodegenStart() {
    _builder.onCodegenStart();
  }

  /// Generates JavaScript code for `work.element`.
  /// Using the ssa builder, optimizer and codegenerator.
  js.Fun compile(CodegenWorkItem work, ClosedWorld closedWorld) {
    HGraph graph = _builder.build(work, closedWorld);
    if (graph == null) return null;
    optimizer.optimize(work, graph, closedWorld);
    MemberEntity element = work.element;
    js.Expression result = generator.generateCode(work, graph, closedWorld);
    if (element is MethodElement) {
      // TODO(sigmund): replace by kernel transformer when `useKernelInSsa` is
      // true.
      result =
          backend.rewriteAsync(closedWorld.commonElements, element, result);
    }
    return result;
  }

  Iterable<CompilerTask> get tasks {
    return <CompilerTask>[_builder, optimizer, generator];
  }
}

abstract class SsaBuilder {
  /// Creates the [HGraph] for [work] or returns `null` if no code is needed
  /// for [work].
  HGraph build(CodegenWorkItem work, ClosedWorld closedWorld);
}

class SsaBuilderTask extends CompilerTask {
  final JavaScriptBackend _backend;
  final SourceInformationStrategy _sourceInformationFactory;
  SsaBuilder _builder;

  SsaBuilderTask(this._backend, this._sourceInformationFactory)
      : super(_backend.compiler.measurer);

  void onCodegenStart() {
    _builder = _backend.compiler.backendStrategy
        .createSsaBuilder(this, _backend, _sourceInformationFactory);
  }

  /// Creates the [HGraph] for [work] or returns `null` if no code is needed
  /// for [work].
  HGraph build(CodegenWorkItem work, ClosedWorld closedWorld) {
    return _builder.build(work, closedWorld);
  }
}

abstract class SsaBuilderFieldMixin {
  ConstantValue getFieldInitialConstantValue(covariant FieldEntity field);

  /// Handle field initializer of [element]. Returns `true` if no code
  /// is needed for the field.
  ///
  /// If [element] is a field with a constant initializer, the value is
  /// registered with the world impact. Otherwise the cyclic-throw helper is
  /// registered for the lazy value computation.
  ///
  /// If the field is constant, no code is needed for the field and the method
  /// returns `true`.
  bool handleConstantField(
      MemberEntity element, CodegenRegistry registry, ClosedWorld closedWorld) {
    if (element.isField) {
      ConstantValue initialValue = getFieldInitialConstantValue(element);
      if (initialValue != null) {
        registry.worldImpact
            .registerConstantUse(new ConstantUse.init(initialValue));
        // We don't need to generate code for static or top-level
        // variables. For instance variables, we may need to generate
        // the checked setter.
        if (element.isStatic || element.isTopLevel) {
          /// No code is created for this field: All references inline the
          /// constant value.
          return true;
        }
      } else {
        // If the constant-handler was not able to produce a result we have to
        // go through the builder (below) to generate the lazy initializer for
        // the static variable.
        // We also need to register the use of the cyclic-error helper.
        registry.worldImpact.registerStaticUse(new StaticUse.staticInvoke(
            closedWorld.commonElements.cyclicThrowHelper,
            CallStructure.ONE_ARG));
      }
    }
    return false;
  }
}
