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

// TODO(askesc): We should not need to call the constant evaluator
// explicitly once constant-update-2018 is shipped.
import 'package:front_end/src/api_prototype/constant_evaluator.dart'
    show ConstantEvaluator, SimpleErrorReporter;

import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart';
import 'package:kernel/target/targets.dart';
import 'package:kernel/type_environment.dart';
import 'kernel_helpers.dart';

/// Implements constant evaluation for dev compiler:
///
/// [isConstant] determines if an expression is constant.
/// [evaluate] computes the value of a constant expression, if available.
class DevCompilerConstants {
  final _ConstantVisitor _visitor;
  final ConstantEvaluator _evaluator;

  DevCompilerConstants(
      TypeEnvironment types, Map<String, String> declaredVariables)
      : _visitor = _ConstantVisitor(types.coreTypes),
        _evaluator = ConstantEvaluator(const DevCompilerConstantsBackend(),
            declaredVariables, types, false, const _ErrorReporter());

  /// Determines if an expression is constant.
  bool isConstant(Expression e) => _visitor.isConstant(e);

  /// Evaluates [e] to find its constant value, returning `null` if evaluation
  /// failed, or if the constant was unavailable.
  ///
  /// Returns [NullConstant] to represent the `null` value.
  ///
  /// To avoid performance costs associated with try+catch on invalid constant
  /// evaluation, call this after [isConstant] is known to be true.
  Constant evaluate(Expression e, {bool cache = false}) {
    if (e == null) return null;

    try {
      var result = cache ? _evaluator.evaluate(e) : e.accept(_evaluator);
      return result is UnevaluatedConstant ? null : result;
    } on _AbortCurrentEvaluation {
      // TODO(jmesserly): the try+catch is necessary because the front end is
      // not issuing sufficient errors, so the constant evaluation can fail.
      //
      // It can also be caused by methods in the evaluator that don't understand
      // unavailable constants.
      return null;
    } on NoSuchMethodError {
      // TODO(jmesserly): this is probably the same issue as above, but verify
      // that it's fixed once Kernel does constant evaluation.
      return null;
    }
  }

  /// If [node] is an annotation with a field named `name`, returns that field's
  /// value.
  ///
  /// This assumes the `name` field is populated from a named argument `name:`
  /// or from the first positional argument.
  ///
  /// For example:
  ///
  ///     class MyAnnotation {
  ///       final String name;
  ///       // ...
  ///       const MyAnnotation(this.name/*, ... other params ... */);
  ///     }
  ///
  ///     @MyAnnotation('FooBar')
  ///     main() { ... }
  ///
  /// Given the node for `@MyAnnotation('FooBar')` this will return `'FooBar'`.
  String getNameFromAnnotation(ConstructorInvocation node) {
    if (node == null) return null;

    // TODO(jmesserly): this does not use the normal evaluation engine, because
    // it won't work if we don't have the const constructor body available.
    //
    // We may need to address this in the kernel outline files.
    Expression first;
    var named = node.arguments.named;
    if (named.isNotEmpty) {
      first =
          named.firstWhere((n) => n.name == 'name', orElse: () => null)?.value;
    }
    var positional = node.arguments.positional;
    if (positional.isNotEmpty) first ??= positional[0];
    if (first != null) {
      first = _followConstFields(first);
      if (first is StringLiteral) return first.value;
    }
    return null;
  }

  Expression _followConstFields(Expression expr) {
    if (expr is StaticGet) {
      var target = expr.target;
      if (target is Field) {
        return _followConstFields(target.initializer);
      }
    }
    return expr;
  }
}

/// Finds constant expressions as defined in Dart language spec 4th ed,
/// 16.1 Constants.
class _ConstantVisitor extends ExpressionVisitor<bool> {
  final CoreTypes coreTypes;
  _ConstantVisitor(this.coreTypes);

  bool isConstant(Expression e) => e.accept(this);

  defaultExpression(node) => false;
  defaultBasicLiteral(node) => true;
  visitTypeLiteral(node) => true; // TODO(jmesserly): deferred libraries?
  visitSymbolLiteral(node) => true;
  visitListLiteral(node) => node.isConst;
  visitMapLiteral(node) => node.isConst;
  visitStaticInvocation(node) {
    return node.isConst ||
        node.target == coreTypes.identicalProcedure &&
            node.arguments.positional.every(isConstant) ||
        isFromEnvironmentInvocation(coreTypes, node) &&
            node.arguments.positional.every(isConstant) &&
            node.arguments.named.every((n) => isConstant(n.value));
  }

  visitDirectMethodInvocation(node) {
    return node.receiver is BasicLiteral &&
        isOperatorMethodName(node.name.name) &&
        node.arguments.positional.every((p) => p is BasicLiteral);
  }

  visitMethodInvocation(node) {
    return node.receiver is BasicLiteral &&
        isOperatorMethodName(node.name.name) &&
        node.arguments.positional.every((p) => p is BasicLiteral);
  }

  visitConstructorInvocation(node) => node.isConst;
  visitStringConcatenation(node) =>
      node.expressions.every((e) => e is BasicLiteral);
  visitStaticGet(node) {
    var target = node.target;
    return target is Procedure || target is Field && target.isConst;
  }

  visitVariableGet(node) => node.variable.isConst;
  visitNot(node) {
    var operand = node.operand;
    return operand is BoolLiteral ||
        operand is DirectMethodInvocation &&
            visitDirectMethodInvocation(operand) ||
        operand is MethodInvocation && visitMethodInvocation(operand);
  }

  visitLogicalExpression(node) =>
      node.left is BoolLiteral && node.right is BoolLiteral;
  visitConditionalExpression(node) =>
      node.condition is BoolLiteral &&
      node.then is BoolLiteral &&
      node.otherwise is BoolLiteral;

  visitLet(Let node) {
    var init = node.variable.initializer;
    return (init == null || isConstant(init)) && isConstant(node.body);
  }
}

/// Implement the class for compiler specific behavior.
class DevCompilerConstantsBackend extends ConstantsBackend {
  const DevCompilerConstantsBackend();

  @override
  NumberSemantics get numberSemantics => NumberSemantics.js;
}

class _ErrorReporter extends SimpleErrorReporter {
  const _ErrorReporter();

  @override
  report(context, message, node) => throw const _AbortCurrentEvaluation();
}

// TODO(jmesserly): this class is private in Kernel constants library, so
// we have our own version.
class _AbortCurrentEvaluation {
  const _AbortCurrentEvaluation();
}
