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

// @dart = 2.10

import 'package:front_end/src/api_prototype/constant_evaluator.dart' as ir;
import 'package:front_end/src/api_unstable/dart2js.dart' as ir;
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/src/printer.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;

import '../environment.dart';
import '../kernel/dart2js_target.dart';

typedef ReportErrorFunction = void Function(
    ir.LocatedMessage message, List<ir.LocatedMessage> context);

class Dart2jsConstantEvaluator extends ir.ConstantEvaluator {
  final bool _supportReevaluationForTesting;

  bool requiresConstant;

  Dart2jsConstantEvaluator(ir.Component component,
      ir.TypeEnvironment typeEnvironment, ReportErrorFunction reportError,
      {Environment environment,
      bool supportReevaluationForTesting = false,
      ir.EvaluationMode evaluationMode})
      : _supportReevaluationForTesting = supportReevaluationForTesting,
        assert(evaluationMode != null),
        super(
            const Dart2jsDartLibrarySupport(),
            const Dart2jsConstantsBackend(supportsUnevaluatedConstants: false),
            component,
            environment?.definitions ?? const {},
            typeEnvironment,
            ErrorReporter(reportError),
            enableTripleShift: true,
            evaluationMode: evaluationMode);

  @override
  ErrorReporter get errorReporter => super.errorReporter;

  /// Evaluates [node] to a constant in the given [staticTypeContext].
  ///
  /// If [requireConstant] is `true`, an error is reported if [node] is not
  /// a valid constant. Otherwise, `null` if [node] is not a valid constant.
  ///
  /// If [replaceImplicitConstant] is `true`, if [node] is not a constant
  /// expression but evaluates to a constant, [node] is replaced with an
  /// [ir.ConstantExpression] holding the constant. Otherwise the [node] is not
  /// replaced even when it evaluated to a constant.
  @override
  ir.Constant evaluate(
      ir.StaticTypeContext staticTypeContext, ir.Expression node,
      {ir.TreeNode contextNode,
      bool requireConstant = true,
      bool replaceImplicitConstant = true}) {
    errorReporter.requiresConstant = requireConstant;
    if (node is ir.ConstantExpression) {
      ir.Constant constant = node.constant;
      if (constant is ir.UnevaluatedConstant) {
        ir.Constant result = super.evaluate(
            staticTypeContext, constant.expression,
            contextNode: contextNode);
        assert(
            result is ir.UnevaluatedConstant ||
                !result.accept(const UnevaluatedConstantFinder()),
            "Invalid constant result $result from ${constant.expression}.");
        if (!_supportReevaluationForTesting) {
          node.constant = result;
        }
        return result;
      }
      return constant;
    }
    if (requireConstant) {
      return super.evaluate(staticTypeContext, node, contextNode: contextNode);
    } else {
      try {
        ir.Constant constant =
            super.evaluate(staticTypeContext, node, contextNode: contextNode);
        if (constant is ir.UnevaluatedConstant &&
            constant.expression is ir.InvalidExpression) {
          return null;
        }
        if (constant != null && replaceImplicitConstant) {
          // Note: Using [replaceWith] is slow and should be avoided.
          node.replaceWith(ir.ConstantExpression(
              constant, node.getStaticType(staticTypeContext))
            ..fileOffset = node.fileOffset);
        }
        return constant;
      } catch (e) {
        return null;
      }
    }
  }
}

class ErrorReporter implements ir.ErrorReporter {
  final ReportErrorFunction _reportError;
  bool requiresConstant;

  ErrorReporter(this._reportError);

  @override
  void report(ir.LocatedMessage message, [List<ir.LocatedMessage> context]) {
    if (requiresConstant) {
      _reportError(message, context);
    }
  }
}

/// [ir.Constant] visitor that returns `true` if the visitor constant contains
/// an [ir.UnevaluatedConstant].
class UnevaluatedConstantFinder extends ir.ConstantVisitor<bool> {
  const UnevaluatedConstantFinder();

  @override
  bool defaultConstant(ir.Constant node) => false;

  @override
  bool visitUnevaluatedConstant(ir.UnevaluatedConstant node) => true;

  @override
  bool visitInstantiationConstant(ir.InstantiationConstant node) {
    return node.tearOffConstant.accept(this);
  }

  @override
  bool visitInstanceConstant(ir.InstanceConstant node) {
    for (ir.Constant value in node.fieldValues.values) {
      if (value.accept(this)) {
        return true;
      }
    }
    return false;
  }

  @override
  bool visitSetConstant(ir.SetConstant node) {
    for (ir.Constant value in node.entries) {
      if (value.accept(this)) {
        return true;
      }
    }
    return false;
  }

  @override
  bool visitListConstant(ir.ListConstant node) {
    for (ir.Constant value in node.entries) {
      if (value.accept(this)) {
        return true;
      }
    }
    return false;
  }

  @override
  bool visitMapConstant(ir.MapConstant node) {
    for (ir.ConstantMapEntry entry in node.entries) {
      if (entry.key.accept(this)) {
        return true;
      }
      if (entry.value.accept(this)) {
        return true;
      }
    }
    return false;
  }
}

/// Class to represent a reference to a constant in allocation nodes.
///
/// This class is needed in order to support serialization of references to
/// constant nodes. Since the constant nodes are not [ir.TreeNode]s we can only
/// serialize the constants as values which would bypass by the canonicalization
/// performed by the CFE. This class extends only as a trick to easily pass
/// it through serialization.
///
/// By adding a reference to the constant expression in which the constant
/// occurred, we can serialize references to constants in two steps: a reference
/// to the constant expression followed by an index of the referred constant
/// in the traversal order of the constant held by the constant expression.
///
/// This is used for list, map, and set literals.
class ConstantReference extends ir.TreeNode {
  final ir.ConstantExpression expression;
  final ir.Constant constant;

  ConstantReference(this.expression, this.constant);

  @override
  void visitChildren(ir.Visitor v) {
    throw UnsupportedError("ConstantReference.visitChildren");
  }

  @override
  R accept<R>(ir.TreeVisitor<R> v) {
    throw UnsupportedError("ConstantReference.accept");
  }

  @override
  R accept1<R, A>(ir.TreeVisitor1<R, A> v, A arg) {
    throw UnsupportedError("ConstantReference.accept");
  }

  @override
  transformChildren(ir.Transformer v) {
    throw UnsupportedError("ConstantReference.transformChildren");
  }

  @override
  transformOrRemoveChildren(ir.RemovingTransformer v) {
    throw UnsupportedError("ConstantReference.transformOrRemoveChildren");
  }

  @override
  int get hashCode => 13 * constant.hashCode;

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    return other is ConstantReference && constant == other.constant;
  }

  @override
  String toString() => 'ConstantReference(${toStringInternal()})';

  @override
  String toStringInternal() => 'constant=${constant.toStringInternal()}';

  @override
  String toText(ir.AstTextStrategy strategy) => constant.toText(strategy);

  @override
  void toTextInternal(ir.AstPrinter printer) =>
      constant.toTextInternal(printer);
}
