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

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

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.TypeEnvironment typeEnvironment, ReportErrorFunction reportError,
      {Map<String, String> environment: const {},
      bool enableTripleShift = false,
      bool supportReevaluationForTesting: false})
      : _supportReevaluationForTesting = supportReevaluationForTesting,
        super(
            const Dart2jsConstantsBackend(supportsUnevaluatedConstants: false),
            environment,
            typeEnvironment,
            new ErrorReporter(reportError),
            enableTripleShift: enableTripleShift);

  @override
  ErrorReporter get errorReporter => super.errorReporter;

  @override
  ir.Constant evaluate(
      ir.StaticTypeContext staticTypeContext, ir.Expression node,
      {bool requireConstant: 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);
        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);
    } else {
      try {
        ir.Constant constant = super.evaluate(staticTypeContext, node);
        if (constant is ir.UnevaluatedConstant &&
            constant.expression is ir.InvalidExpression) {
          return null;
        }
        // TODO(johnniwinther,sigmund): Replace [node] with an
        // `ir.ConstantExpression` holding the [constant].
        return constant;
      } catch (e) {
        return null;
      }
    }
  }
}

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

  ErrorReporter(this._reportError);

  @override
  void reportInvalidExpression(ir.InvalidExpression node) {
    // Ignore.
  }

  @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 visitPartialInstantiationConstant(ir.PartialInstantiationConstant 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 new UnsupportedError("ConstantReference.visitChildren");
  }

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

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

  @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(constant=$constant)';
}
