// Copyright (c) 2014, 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.

part of js_ast;

/// Visitor that computes whether two [Node]s are structurally equivalent.
class EquivalenceVisitor implements NodeVisitor1<bool, Node> {
  const EquivalenceVisitor();

  /// Called when [node1] and [node2] are not equivalent.
  ///
  /// Override this to collect or report information on the inequivalent nodes.
  bool failAt(Node node1, Node node2) => false;

  /// Returns whether the non-node values [value1] and [value2] are equivalent.
  bool testValues(Node node1, Object value1, Node node2, Object value2) =>
      value1 == value2;

  /// Returns whether the labels [label1] and [label2] are equivalent.
  bool testLabels(Node node1, String label1, Node node2, String label2) =>
      label1 == label2;

  bool testNodes(Node node1, Node node2) {
    if (identical(node1, node2)) return true;
    if (node1 == null || node2 == null) return failAt(node1, node2);
    return node1.accept1(this, node2);
  }

  bool testNodeLists(List<Node> list1, List<Node> list2) {
    int index = 0;
    while (index < list1.length && index < list2.length) {
      if (!testNodes(list1[index], list2[index])) return false;
      index++;
    }
    if (index < list1.length) {
      return failAt(list1[index], null);
    } else if (index < list2.length) {
      return failAt(list2[index], null);
    }
    return true;
  }

  @override
  bool visitProgram(Program node, Node arg) {
    if (arg is! Program) return failAt(node, arg);
    Program other = arg;
    return testNodeLists(node.body, other.body);
  }

  @override
  bool visitInterpolatedDeclaration(InterpolatedDeclaration node, Node arg) {
    if (arg is! InterpolatedDeclaration) return failAt(node, arg);
    InterpolatedDeclaration other = arg;
    return testValues(node, node.nameOrPosition, other, other.nameOrPosition);
  }

  @override
  bool visitInterpolatedStatement(InterpolatedStatement node, Node arg) {
    if (arg is! InterpolatedStatement) return failAt(node, arg);
    InterpolatedStatement other = arg;
    return testValues(node, node.nameOrPosition, other, other.nameOrPosition);
  }

  @override
  bool visitInterpolatedSelector(InterpolatedSelector node, Node arg) {
    if (arg is! InterpolatedSelector) return failAt(node, arg);
    InterpolatedSelector other = arg;
    return testValues(node, node.nameOrPosition, other, other.nameOrPosition);
  }

  @override
  bool visitInterpolatedParameter(InterpolatedParameter node, Node arg) {
    if (arg is! InterpolatedParameter) return failAt(node, arg);
    InterpolatedParameter other = arg;
    return testValues(node, node.nameOrPosition, other, other.nameOrPosition);
  }

  @override
  bool visitInterpolatedLiteral(InterpolatedLiteral node, Node arg) {
    if (arg is! InterpolatedLiteral) return failAt(node, arg);
    InterpolatedLiteral other = arg;
    return testValues(node, node.nameOrPosition, other, other.nameOrPosition);
  }

  @override
  bool visitInterpolatedExpression(InterpolatedExpression node, Node arg) {
    if (arg is! InterpolatedExpression) return failAt(node, arg);
    InterpolatedExpression other = arg;
    return testValues(node, node.nameOrPosition, other, other.nameOrPosition);
  }

  @override
  bool visitComment(Comment node, Node arg) {
    if (arg is! Comment) return failAt(node, arg);
    Comment other = arg;
    return testValues(node, node.comment, other, other.comment);
  }

  @override
  bool visitAwait(Await node, Node arg) {
    if (arg is! Await) return failAt(node, arg);
    Await other = arg;
    return testNodes(node.expression, other.expression);
  }

  @override
  bool visitRegExpLiteral(RegExpLiteral node, Node arg) {
    if (arg is! RegExpLiteral) return failAt(node, arg);
    RegExpLiteral other = arg;
    return testValues(node, node.pattern, other, other.pattern);
  }

  @override
  bool visitProperty(Property node, Node arg) {
    if (arg is! Property) return failAt(node, arg);
    Property other = arg;
    return testNodes(node.name, other.name) &&
        testNodes(node.value, other.value);
  }

  @override
  bool visitMethodDefinition(MethodDefinition node, Node arg) {
    if (arg is! MethodDefinition) return failAt(node, arg);
    MethodDefinition other = arg;
    return testNodes(node.name, other.name) &&
        testNodes(node.function, other.function);
  }

  @override
  bool visitObjectInitializer(ObjectInitializer node, Node arg) {
    if (arg is! ObjectInitializer) return failAt(node, arg);
    ObjectInitializer other = arg;
    return testNodeLists(node.properties, other.properties);
  }

  @override
  bool visitArrayHole(ArrayHole node, Node arg) {
    if (arg is! ArrayHole) return failAt(node, arg);
    return true;
  }

  @override
  bool visitArrayInitializer(ArrayInitializer node, Node arg) {
    if (arg is! ArrayInitializer) return failAt(node, arg);
    ArrayInitializer other = arg;
    return testNodeLists(node.elements, other.elements);
  }

  @override
  bool visitName(Name node, Node arg) {
    if (arg is! Name) return failAt(node, arg);
    Name other = arg;
    return testValues(node, node.key, other, other.key);
  }

  @override
  bool visitParentheses(Parentheses node, Node arg) {
    if (arg is! Parentheses) return failAt(node, arg);
    Parentheses other = arg;
    return testValues(node, node.enclosed, other, other.enclosed);
  }

  @override
  bool visitStringConcatenation(StringConcatenation node, Node arg) {
    if (arg is! StringConcatenation) return failAt(node, arg);
    StringConcatenation other = arg;
    return testNodeLists(node.parts, other.parts);
  }

  @override
  bool visitLiteralNull(LiteralNull node, Node arg) {
    if (arg is! LiteralNull) return failAt(node, arg);
    return true;
  }

  @override
  bool visitLiteralNumber(LiteralNumber node, Node arg) {
    if (arg is! LiteralNumber) return failAt(node, arg);
    LiteralNumber other = arg;
    return testValues(node, node.value, other, other.value);
  }

  @override
  bool visitLiteralString(LiteralString node, Node arg) {
    if (arg is! LiteralString) return failAt(node, arg);
    LiteralString other = arg;
    return testValues(node, node.value, other, other.value);
  }

  @override
  bool visitLiteralBool(LiteralBool node, Node arg) {
    if (arg is! LiteralBool) return failAt(node, arg);
    LiteralBool other = arg;
    return testValues(node, node.value, other, other.value);
  }

  @override
  bool visitDeferredString(DeferredString node, Node arg) {
    if (arg is! DeferredString) return failAt(node, arg);
    DeferredString other = arg;
    return testValues(node, node.value, other, other.value);
  }

  @override
  bool visitDeferredNumber(DeferredNumber node, Node arg) {
    if (arg is! DeferredNumber) return failAt(node, arg);
    DeferredNumber other = arg;
    return testValues(node, node.value, other, other.value);
  }

  @override
  bool visitDeferredExpression(DeferredExpression node, Node arg) {
    if (arg is! DeferredExpression) return failAt(node, arg);
    DeferredExpression other = arg;
    return testNodes(node.value, other.value);
  }

  @override
  bool visitDeferredStatement(DeferredStatement node, Node arg) {
    if (arg is! DeferredStatement) return failAt(node, arg);
    DeferredStatement other = arg;
    return testNodes(node.statement, other.statement);
  }

  @override
  bool visitFun(Fun node, Node arg) {
    if (arg is! Fun) return failAt(node, arg);
    Fun other = arg;
    return testNodeLists(node.params, other.params) &&
        testNodes(node.body, other.body) &&
        testValues(node, node.asyncModifier, other, other.asyncModifier);
  }

  @override
  bool visitArrowFunction(ArrowFunction node, Node arg) {
    if (arg is! ArrowFunction) return failAt(node, arg);
    ArrowFunction other = arg;
    return testNodeLists(node.params, other.params) &&
        testNodes(node.body, other.body) &&
        testValues(node, node.asyncModifier, other, other.asyncModifier);
  }

  @override
  bool visitNamedFunction(NamedFunction node, Node arg) {
    if (arg is! NamedFunction) return failAt(node, arg);
    NamedFunction other = arg;
    return testNodes(node.name, other.name) &&
        testNodes(node.function, other.function);
  }

  @override
  bool visitAccess(PropertyAccess node, Node arg) {
    if (arg is! PropertyAccess) return failAt(node, arg);
    PropertyAccess other = arg;
    return testNodes(node.receiver, other.receiver) &&
        testNodes(node.selector, other.selector);
  }

  @override
  bool visitParameter(Parameter node, Node arg) {
    if (arg is! Parameter) return failAt(node, arg);
    Parameter other = arg;
    return testValues(node, node.name, other, other.name);
  }

  @override
  bool visitVariableDeclaration(VariableDeclaration node, Node arg) {
    if (arg is! VariableDeclaration) return failAt(node, arg);
    VariableDeclaration other = arg;
    return testValues(node, node.name, other, other.name) &&
        testValues(node, node.allowRename, other, other.allowRename);
  }

  @override
  bool visitThis(This node, Node arg) {
    if (arg is! This) return failAt(node, arg);
    return true;
  }

  @override
  bool visitVariableUse(VariableUse node, Node arg) {
    if (arg is! VariableUse) return failAt(node, arg);
    VariableUse other = arg;
    return testValues(node, node.name, other, other.name);
  }

  @override
  bool visitPostfix(Postfix node, Node arg) {
    if (arg is! Postfix) return failAt(node, arg);
    Postfix other = arg;
    return testValues(node, node.op, other, other.op) &&
        testNodes(node.argument, other.argument);
  }

  @override
  bool visitPrefix(Prefix node, Node arg) {
    if (arg is! Prefix) return failAt(node, arg);
    Prefix other = arg;
    return testValues(node, node.op, other, other.op) &&
        testNodes(node.argument, other.argument);
  }

  @override
  bool visitBinary(Binary node, Node arg) {
    if (arg is! Binary) return failAt(node, arg);
    Binary other = arg;
    return testNodes(node.left, other.left) &&
        testValues(node, node.op, other, other.op) &&
        testNodes(node.right, other.right);
  }

  @override
  bool visitCall(Call node, Node arg) {
    if (arg is! Call) return failAt(node, arg);
    Call other = arg;
    return testNodes(node.target, other.target) &&
        testNodeLists(node.arguments, other.arguments);
  }

  @override
  bool visitNew(New node, Node arg) {
    if (arg is! New) return failAt(node, arg);
    New other = arg;
    return testNodes(node.target, other.target) &&
        testNodeLists(node.arguments, other.arguments);
  }

  @override
  bool visitConditional(Conditional node, Node arg) {
    if (arg is! Conditional) return failAt(node, arg);
    Conditional other = arg;
    return testNodes(node.condition, other.condition) &&
        testNodes(node.then, other.then) &&
        testNodes(node.otherwise, other.otherwise);
  }

  @override
  bool visitVariableInitialization(VariableInitialization node, Node arg) {
    if (arg is! VariableInitialization) return failAt(node, arg);
    VariableInitialization other = arg;
    return testNodes(node.declaration, other.declaration) &&
        testNodes(node.value, other.value);
  }

  @override
  bool visitAssignment(Assignment node, Node arg) {
    if (arg is! Assignment) return failAt(node, arg);
    Assignment other = arg;
    return testNodes(node.leftHandSide, other.leftHandSide) &&
        testValues(node, node.op, other, other.op) &&
        testNodes(node.value, other.value);
  }

  @override
  bool visitVariableDeclarationList(VariableDeclarationList node, Node arg) {
    if (arg is! VariableDeclarationList) return failAt(node, arg);
    VariableDeclarationList other = arg;
    return testNodeLists(node.declarations, other.declarations);
  }

  @override
  bool visitLiteralExpression(LiteralExpression node, Node arg) {
    if (arg is! LiteralExpression) return failAt(node, arg);
    LiteralExpression other = arg;
    return testValues(node, node.template, other, other.template);
  }

  @override
  bool visitDartYield(DartYield node, Node arg) {
    if (arg is! DartYield) return failAt(node, arg);
    DartYield other = arg;
    return testNodes(node.expression, other.expression) &&
        testValues(node, node.hasStar, other, other.hasStar);
  }

  @override
  bool visitLiteralStatement(LiteralStatement node, Node arg) {
    if (arg is! LiteralStatement) return failAt(node, arg);
    LiteralStatement other = arg;
    return testValues(node, node.code, other, other.code);
  }

  @override
  bool visitLabeledStatement(LabeledStatement node, Node arg) {
    if (arg is! LabeledStatement) return failAt(node, arg);
    LabeledStatement other = arg;
    return testLabels(node, node.label, other, other.label) &&
        testNodes(node.body, other.body);
  }

  @override
  bool visitFunctionDeclaration(FunctionDeclaration node, Node arg) {
    if (arg is! FunctionDeclaration) return failAt(node, arg);
    FunctionDeclaration other = arg;
    return testNodes(node.name, other.name) &&
        testNodes(node.function, other.function);
  }

  @override
  bool visitDefault(Default node, Node arg) {
    if (arg is! Default) return failAt(node, arg);
    Default other = arg;
    return testNodes(node.body, other.body);
  }

  @override
  bool visitCase(Case node, Node arg) {
    if (arg is! Case) return failAt(node, arg);
    Case other = arg;
    return testNodes(node.expression, other.expression) &&
        testNodes(node.body, other.body);
  }

  @override
  bool visitSwitch(Switch node, Node arg) {
    if (arg is! Switch) return failAt(node, arg);
    Switch other = arg;
    return testNodes(node.key, other.key) &&
        testNodeLists(node.cases, other.cases);
  }

  @override
  bool visitCatch(Catch node, Node arg) {
    if (arg is! Catch) return failAt(node, arg);
    Catch other = arg;
    return testNodes(node.declaration, other.declaration) &&
        testNodes(node.body, other.body);
  }

  @override
  bool visitTry(Try node, Node arg) {
    if (arg is! Try) return failAt(node, arg);
    Try other = arg;
    return testNodes(node.body, other.body) &&
        testNodes(node.catchPart, other.catchPart) &&
        testNodes(node.finallyPart, other.finallyPart);
  }

  @override
  bool visitThrow(Throw node, Node arg) {
    if (arg is! Throw) return failAt(node, arg);
    Throw other = arg;
    return testNodes(node.expression, other.expression);
  }

  @override
  bool visitReturn(Return node, Node arg) {
    if (arg is! Return) return failAt(node, arg);
    Return other = arg;
    return testNodes(node.value, other.value);
  }

  @override
  bool visitBreak(Break node, Node arg) {
    if (arg is! Break) return failAt(node, arg);
    Break other = arg;
    return testLabels(node, node.targetLabel, other, other.targetLabel);
  }

  @override
  bool visitContinue(Continue node, Node arg) {
    if (arg is! Continue) return failAt(node, arg);
    Continue other = arg;
    return testLabels(node, node.targetLabel, other, other.targetLabel);
  }

  @override
  bool visitDo(Do node, Node arg) {
    if (arg is! Do) return failAt(node, arg);
    Do other = arg;
    return testNodes(node.condition, other.condition) &&
        testNodes(node.body, other.body);
  }

  @override
  bool visitWhile(While node, Node arg) {
    if (arg is! While) return failAt(node, arg);
    While other = arg;
    return testNodes(node.condition, other.condition) &&
        testNodes(node.body, other.body);
  }

  @override
  bool visitForIn(ForIn node, Node arg) {
    if (arg is! ForIn) return failAt(node, arg);
    ForIn other = arg;
    return testNodes(node.leftHandSide, other.leftHandSide) &&
        testNodes(node.object, other.object) &&
        testNodes(node.body, other.body);
  }

  @override
  bool visitFor(For node, Node arg) {
    if (arg is! For) return failAt(node, arg);
    For other = arg;
    return testNodes(node.init, other.init) &&
        testNodes(node.condition, other.condition) &&
        testNodes(node.update, other.update) &&
        testNodes(node.body, other.body);
  }

  @override
  bool visitIf(If node, Node arg) {
    if (arg is! If) return failAt(node, arg);
    If other = arg;
    return testNodes(node.condition, other.condition) &&
        testNodes(node.then, other.then) &&
        testNodes(node.otherwise, other.otherwise);
  }

  @override
  bool visitEmptyStatement(EmptyStatement node, Node arg) {
    if (arg is! EmptyStatement) return failAt(node, arg);
    return true;
  }

  @override
  bool visitExpressionStatement(ExpressionStatement node, Node arg) {
    if (arg is! ExpressionStatement) return failAt(node, arg);
    ExpressionStatement other = arg;
    return testNodes(node.expression, other.expression);
  }

  @override
  bool visitBlock(Block node, Node arg) {
    if (arg is! Block) return failAt(node, arg);
    Block other = arg;
    return testNodeLists(node.statements, other.statements);
  }
}
