// Copyright (c) 2018, 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.

import 'package:kernel/ast.dart' as ir;

import '../constants/values.dart';
import '../js_model/elements.dart' show JsToFrontendMap, JField;
import '../kernel/element_map.dart';
import '../kernel/kernel_strategy.dart';
import '../kernel/kelements.dart' show KClass, KField;
import '../options.dart';
import '../serialization/serialization.dart';

abstract class AllocatorAnalysis {}

/// AllocatorAnalysis
///
/// Analysis to determine features of the allocator functions. The allocator
/// function takes parameters for each field initializer and initializes the
/// fields.  Parameters may be omitted if the initializer is always the same
/// constant value.  How the allocator is emitted will determine what kind of
/// constants can be handled.  The initial implementation only permits `null`.

// TODO(sra): Analysis to determine field order. Current field order is
// essentially declaration order, subclass first. We can reorder fields so that
// fields initialized with the same constant are together to allow chained
// initialization. Fields of a class and superclass can be reordered to allow
// chaining, e.g.
//
//     this.x = this.z = null;
//
class KAllocatorAnalysis implements AllocatorAnalysis {
  final KernelToElementMap _elementMap;

  final Map<KField, ConstantValue> _fixedInitializers =
      <KField, ConstantValue>{};

  KAllocatorAnalysis(KernelFrontEndStrategy kernelStrategy)
      : _elementMap = kernelStrategy.elementMap;

  // Register class during resolution. Use simple syntactic analysis to find
  // null-initialized fields.
  void registerInstantiatedClass(KClass class_) {
    ir.Class classNode = _elementMap.getClassNode(class_);

    Set<ir.Field> nulls = new Set<ir.Field>();
    for (ir.Field field in classNode.fields) {
      if (!field.isInstanceMember) continue;
      ir.Expression initializer = field.initializer;
      if (initializer == null || initializer is ir.NullLiteral) {
        nulls.add(field);
      }
    }

    for (ir.Constructor constructor in classNode.constructors) {
      for (ir.Initializer initializer in constructor.initializers) {
        if (initializer is ir.FieldInitializer) {
          // TODO(sra): Check explicit initializer value to see if consistent
          // over all constructors.
          nulls.remove(initializer.field);
        }
      }
    }

    for (var fieldNode in nulls) {
      _fixedInitializers[_elementMap.getField(fieldNode)] =
          const NullConstantValue();
    }
  }
}

class JAllocatorAnalysis implements AllocatorAnalysis {
  /// Tag used for identifying serialized [JAllocatorAnalysis] objects in a
  /// debugging data stream.
  static const String tag = 'allocator-analysis';

  // --csp and --fast-startup have different constraints to the generated code.
  final CompilerOptions _options;
  final Map<JField, ConstantValue> _fixedInitializers =
      <JField, ConstantValue>{};

  JAllocatorAnalysis._(this._options);

  /// Deserializes a [JAllocatorAnalysis] object from [source].
  factory JAllocatorAnalysis.readFromDataSource(
      DataSource source, CompilerOptions options) {
    source.begin(tag);
    JAllocatorAnalysis analysis = new JAllocatorAnalysis._(options);
    int fieldCount = source.readInt();
    for (int i = 0; i < fieldCount; i++) {
      JField field = source.readMember();
      // TODO(sra): Deserialize constant, when non-null is supported.
      ConstantValue value = const NullConstantValue();
      analysis._fixedInitializers[field] = value;
    }
    source.end(tag);
    return analysis;
  }

  /// Serializes this [JAllocatorAnalysis] to [sink].
  void writeToDataSink(DataSink sink) {
    sink.begin(tag);
    sink.writeInt(_fixedInitializers.length);
    _fixedInitializers.forEach((JField field, ConstantValue value) {
      sink.writeMember(field);
      // TODO(sra): Serialize constant, when non-null is supported.
      assert(value.isNull);
    });
    sink.end(tag);
  }

  static JAllocatorAnalysis from(KAllocatorAnalysis kAnalysis,
      JsToFrontendMap map, CompilerOptions options) {
    var result = new JAllocatorAnalysis._(options);

    kAnalysis._fixedInitializers.forEach((KField kField, ConstantValue value) {
      // TODO(sra): Translate constant, but Null does not need translating.
      if (value.isNull) {
        JField jField = map.toBackendMember(kField);
        if (jField != null) {
          result._fixedInitializers[jField] = value;
        }
      }
    });

    return result;
  }

  bool get _isEnabled {
    if (_options.useContentSecurityPolicy && !_options.useStartupEmitter) {
      // TODO(sra): Refactor csp 'precompiled' constructor generation to allow
      // in-allocator initialization.
      return false;
    }
    return true;
  }
  // TODO(sra): Add way to let injected fields be initialized to a constant in
  // allocator.

  bool isInitializedInAllocator(JField field) {
    if (!_isEnabled) return false;
    return _fixedInitializers[field] != null;
  }

  /// Return constant for a field initialized in allocator. Returns `null` for
  /// fields not initialized in allocator.
  ConstantValue initializerValue(JField field) {
    assert(_isEnabled);
    return _fixedInitializers[field];
  }
}
