// 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/core_types.dart';
import 'package:kernel/kernel.dart';
import 'package:kernel/transformations/constants.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 = new _ConstantVisitor(types.coreTypes),
        _evaluator = new _ConstantEvaluator(types, declaredVariables);

  /// 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 identical(result, _evaluator.unavailableConstant) ? 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;
    }
  }

  /// 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);
  }
}

/// The visitor that evaluates constants, building on Kernel's
/// [ConstantEvaluator] class (used by the VM) and fixing some of its behavior
/// to work better for DDC.
//
// TODO(jmesserly): make some changes in the base class to make it a better fit
// for compilers like DDC?
class _ConstantEvaluator extends ConstantEvaluator {
  final Map<String, String> declaredVariables;

  /// Used to denote an unavailable constant value from another module
  ///
  // TODO(jmesserly): this happens when we try to evaluate constant values from
  // an external library, that was from an outline kernel file. The kernel file
  // does not contain the initializer value of the constant.
  final Constant unavailableConstant;

  _ConstantEvaluator(TypeEnvironment types, this.declaredVariables,
      {bool enableAsserts})
      : unavailableConstant = new InstanceConstant(
            types.coreTypes.index
                .getClass('dart:core', '_ConstantExpressionError')
                .reference,
            [],
            {}),
        super(new _ConstantsBackend(types.coreTypes), types, types.coreTypes,
            true, enableAsserts, const _ErrorReporter()) {
    env = new EvaluationEnvironment();
  }

  @override
  visitVariableGet(node) {
    // The base evaluator expects that variable declarations are visited during
    // the transformation step, so it doesn't handle constant variables.
    // Instead handle them here.
    if (node.variable.isConst) {
      return evaluate(node.variable.initializer);
    }
    // Fall back to the base evaluator for other cases (e.g. parameters of a
    // constant constructor).
    return super.visitVariableGet(node);
  }

  @override
  visitStaticGet(StaticGet node) {
    // Handle unavailable field constants. This happens if an external library
    // only has its outline available.
    var target = node.target;
    if (target is Field &&
        target.isConst &&
        target.isInExternalLibrary &&
        target.initializer == null) {
      return unavailableConstant;
    }
    return super.visitStaticGet(node);
  }

  @override
  visitConstructorInvocation(ConstructorInvocation node) {
    // Handle unavailable constructor bodies.
    // This happens if an external library only has its outline available.
    var target = node.target;
    if (target.isConst &&
        target.isInExternalLibrary &&
        target.function.body is EmptyStatement &&
        target.initializers.isEmpty) {
      return unavailableConstant;
    }
    return super.visitConstructorInvocation(node);
  }

  @override
  visitStaticInvocation(node) {
    // Handle int/bool/String.fromEnvironment constructors.
    //
    // (The VM handles this via its `native` calls and implements it in
    // VmConstantsBackend.buildConstantForNative.)
    var target = node.target;
    if (isFromEnvironmentInvocation(coreTypes, node)) {
      var firstArg = evaluatePositionalArguments(node.arguments)[0];
      var defaultArg = evaluateNamedArguments(node.arguments)['defaultValue'];

      var varName = (firstArg as StringConstant).value;
      var value = declaredVariables[varName];
      var targetClass = target.enclosingClass;

      if (targetClass == coreTypes.stringClass) {
        if (value != null) return canonicalize(new StringConstant(value));
        return defaultArg ?? nullConstant;
      } else if (targetClass == coreTypes.intClass) {
        var intValue = int.parse(value ?? '', onError: (_) => null);
        if (intValue != null) return canonicalize(new IntConstant(intValue));
        return defaultArg ?? nullConstant;
      } else if (targetClass == coreTypes.boolClass) {
        if (value == "true") return trueConstant;
        if (value == "false") return falseConstant;
        return defaultArg ?? falseConstant;
      }
    }
    return super.visitStaticInvocation(node);
  }

  @override
  evaluateBinaryNumericOperation(String op, num a, num b, TreeNode node) {
    // Use doubles to match JS number semantics.
    return super
        .evaluateBinaryNumericOperation(op, a.toDouble(), b.toDouble(), node);
  }

  @override
  canonicalize(Constant constant) {
    if (constant is DoubleConstant) {
      // Convert to an integer when possible (matching the runtime behavior
      // of `is int`).
      var d = constant.value;
      if (d.isFinite) {
        var i = d.toInt();
        if (d == i.toDouble()) return super.canonicalize(new IntConstant(i));
      }
    }
    return super.canonicalize(constant);
  }
}

/// Implement the class for compiler specific behavior.
///
/// This is mostly unused by DDC, because we don't use the global constant
/// transformer.
class _ConstantsBackend implements ConstantsBackend {
  final CoreTypes coreTypes;
  final Field symbolNameField;

  _ConstantsBackend(this.coreTypes)
      : symbolNameField = coreTypes.internalSymbolClass.fields
            .firstWhere((f) => f.name.name == '_name');

  @override
  buildConstantForNative(
          nativeName, typeArguments, positionalArguments, namedArguments) =>
      throw new StateError('unreachable'); // DDC does not use VM native syntax

  @override
  buildSymbolConstant(StringConstant value) {
    return new InstanceConstant(
        coreTypes.internalSymbolClass.reference,
        const <DartType>[],
        <Reference, Constant>{symbolNameField.reference: value});
  }

  @override
  lowerMapConstant(constant) => constant;

  @override
  lowerListConstant(constant) => constant;
}

class _ErrorReporter extends ErrorReporterBase {
  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();
}
