package org.checkerframework.dataflow.cfg.node;

/**
 * A visitor for a {@link Node} tree.
 *
 * @param <R> return type of the visitor. Use {@link Void} if the visitor does not have a return
 *     value.
 * @param <P> parameter type of the visitor. Use {@link Void} if the visitor does not have a
 *     parameter.
 */
public interface NodeVisitor<R, P> {
  // Literals
  R visitShortLiteral(ShortLiteralNode n, P p);

  R visitIntegerLiteral(IntegerLiteralNode n, P p);

  R visitLongLiteral(LongLiteralNode n, P p);

  R visitFloatLiteral(FloatLiteralNode n, P p);

  R visitDoubleLiteral(DoubleLiteralNode n, P p);

  R visitBooleanLiteral(BooleanLiteralNode n, P p);

  R visitCharacterLiteral(CharacterLiteralNode n, P p);

  R visitStringLiteral(StringLiteralNode n, P p);

  R visitNullLiteral(NullLiteralNode n, P p);

  // Unary operations
  R visitNumericalMinus(NumericalMinusNode n, P p);

  R visitNumericalPlus(NumericalPlusNode n, P p);

  R visitBitwiseComplement(BitwiseComplementNode n, P p);

  R visitNullChk(NullChkNode n, P p);

  // Binary operations
  R visitStringConcatenate(StringConcatenateNode n, P p);

  R visitNumericalAddition(NumericalAdditionNode n, P p);

  R visitNumericalSubtraction(NumericalSubtractionNode n, P p);

  R visitNumericalMultiplication(NumericalMultiplicationNode n, P p);

  R visitIntegerDivision(IntegerDivisionNode n, P p);

  R visitFloatingDivision(FloatingDivisionNode n, P p);

  R visitIntegerRemainder(IntegerRemainderNode n, P p);

  R visitFloatingRemainder(FloatingRemainderNode n, P p);

  R visitLeftShift(LeftShiftNode n, P p);

  R visitSignedRightShift(SignedRightShiftNode n, P p);

  R visitUnsignedRightShift(UnsignedRightShiftNode n, P p);

  R visitBitwiseAnd(BitwiseAndNode n, P p);

  R visitBitwiseOr(BitwiseOrNode n, P p);

  R visitBitwiseXor(BitwiseXorNode n, P p);

  // Comparison operations
  R visitLessThan(LessThanNode n, P p);

  R visitLessThanOrEqual(LessThanOrEqualNode n, P p);

  R visitGreaterThan(GreaterThanNode n, P p);

  R visitGreaterThanOrEqual(GreaterThanOrEqualNode n, P p);

  R visitEqualTo(EqualToNode n, P p);

  R visitNotEqual(NotEqualNode n, P p);

  // Conditional operations
  R visitConditionalAnd(ConditionalAndNode n, P p);

  R visitConditionalOr(ConditionalOrNode n, P p);

  R visitConditionalNot(ConditionalNotNode n, P p);

  R visitTernaryExpression(TernaryExpressionNode n, P p);

  R visitSwitchExpressionNode(SwitchExpressionNode n, P p);

  R visitAssignment(AssignmentNode n, P p);

  R visitLocalVariable(LocalVariableNode n, P p);

  R visitVariableDeclaration(VariableDeclarationNode n, P p);

  R visitFieldAccess(FieldAccessNode n, P p);

  R visitMethodAccess(MethodAccessNode n, P p);

  R visitArrayAccess(ArrayAccessNode n, P p);

  R visitImplicitThis(ImplicitThisNode n, P p);

  R visitExplicitThis(ExplicitThisNode n, P p);

  R visitSuper(SuperNode n, P p);

  R visitReturn(ReturnNode n, P p);

  R visitLambdaResultExpression(LambdaResultExpressionNode n, P p);

  R visitStringConversion(StringConversionNode n, P p);

  R visitWideningConversion(WideningConversionNode n, P p);

  R visitNarrowingConversion(NarrowingConversionNode n, P p);

  R visitInstanceOf(InstanceOfNode n, P p);

  R visitTypeCast(TypeCastNode n, P p);

  // Blocks

  R visitSynchronized(SynchronizedNode n, P p);

  // Statements
  R visitAssertionError(AssertionErrorNode n, P p);

  R visitThrow(ThrowNode n, P p);

  // Cases
  R visitCase(CaseNode n, P p);

  // Method and constructor invocations
  R visitMethodInvocation(MethodInvocationNode n, P p);

  R visitObjectCreation(ObjectCreationNode n, P p);

  R visitMemberReference(FunctionalInterfaceNode n, P p);

  R visitArrayCreation(ArrayCreationNode n, P p);

  // Type, package and class names
  R visitArrayType(ArrayTypeNode n, P p);

  R visitPrimitiveType(PrimitiveTypeNode n, P p);

  R visitClassName(ClassNameNode n, P p);

  R visitPackageName(PackageNameNode n, P p);

  // Parameterized types
  R visitParameterizedType(ParameterizedTypeNode n, P p);

  // Marker nodes
  R visitMarker(MarkerNode n, P p);

  /**
   * Visits an anonymous/inner/nested class declaration within a method.
   *
   * @param classDeclarationNode the {@link ClassDeclarationNode} to be visited
   * @param p the argument for the operation implemented by this visitor
   * @return the return value of the operation implemented by this visitor
   */
  R visitClassDeclaration(ClassDeclarationNode classDeclarationNode, P p);

  /**
   * Visits an expression that is used as a statement. This node is a marker after the expression
   * node(s).
   *
   * @param n the {@link ExpressionStatementNode} to be visited
   * @param p the argument for the operation implemented by this visitor
   * @return the return value of the operation implemented by this visitor
   */
  R visitExpressionStatement(ExpressionStatementNode n, P p);

  /**
   * Visits a deconstructor pattern node.
   *
   * @param n the {@link DeconstructorPatternNode} to be visited
   * @param p the argument for the operation implemented by this visitor
   * @return the return value of the operation implemented by this visitor
   */
  R visitDeconstructorPattern(DeconstructorPatternNode n, P p);
}
