// 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 = _ConstantVisitor(types.coreTypes),
        _evaluator = _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 = InstanceConstant(
            types.coreTypes.index
                .getClass('dart:core', '_ConstantExpressionError')
                .reference,
            [],
            {}),
        super(_ConstantsBackend(types.coreTypes), types, types.coreTypes, true,
            enableAsserts, const _ErrorReporter()) {
    env = 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(StringConstant(value));
        return defaultArg ?? nullConstant;
      } else if (targetClass == coreTypes.intClass) {
        var intValue = int.tryParse(value ?? '');
        if (intValue != null) return canonicalize(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(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 StateError('unreachable'); // DDC does not use VM native syntax

  @override
  buildSymbolConstant(StringConstant value) {
    return 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();
}
