// 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 supportReevaluationForTesting: false})
      : _supportReevaluationForTesting = supportReevaluationForTesting,
        super(
            const Dart2jsConstantsBackend(supportsUnevaluatedConstants: false),
            environment,
            typeEnvironment,
            new ErrorReporter(reportError));

  @override
  ErrorReporter get errorReporter => super.errorReporter;

  @override
  ir.Constant evaluate(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(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) {
      // TODO(johnniwinther): Handle reporting of compile-time constant
      // evaluation errors.
      return super.evaluate(node);
    } else {
      try {
        return super.evaluate(node);
      } 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)';
}
