/*
 * Copyright (c) 2002,2006 IBM Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 */
package com.ibm.wala.shrike.shrikeBT;

/**
 * @author sfink
 *     <p>Basic functionality we expect of any instruction implementation
 */
public interface IInstruction {

  /** This class is used by IInstruction.visit to dispatch based on the instruction type. */
  @SuppressWarnings("unused")
  abstract class Visitor {
    public void visitConstant(ConstantInstruction instruction) {}

    public void visitGoto(GotoInstruction instruction) {}

    public void visitLocalLoad(ILoadInstruction instruction) {}

    public void visitLocalStore(IStoreInstruction instruction) {}

    public void visitArrayLoad(IArrayLoadInstruction instruction) {}

    public void visitArrayStore(IArrayStoreInstruction instruction) {}

    public void visitPop(PopInstruction instruction) {}

    public void visitDup(DupInstruction instruction) {}

    public void visitSwap(SwapInstruction instruction) {}

    public void visitBinaryOp(IBinaryOpInstruction instruction) {}

    public void visitUnaryOp(IUnaryOpInstruction instruction) {}

    public void visitShift(IShiftInstruction instruction) {}

    public void visitConversion(IConversionInstruction instruction) {}

    public void visitComparison(IComparisonInstruction instruction) {}

    public void visitConditionalBranch(IConditionalBranchInstruction instruction) {}

    public void visitSwitch(SwitchInstruction instruction) {}

    public void visitReturn(ReturnInstruction instruction) {}

    public void visitGet(IGetInstruction instruction) {}

    public void visitPut(IPutInstruction instruction) {}

    public void visitInvoke(IInvokeInstruction instruction) {}

    public void visitNew(NewInstruction instruction) {}

    public void visitArrayLength(ArrayLengthInstruction instruction) {}

    public void visitThrow(ThrowInstruction instruction) {}

    public void visitMonitor(MonitorInstruction instruction) {}

    public void visitCheckCast(ITypeTestInstruction instruction) {}

    public void visitInstanceof(IInstanceofInstruction instruction) {}

    public void visitLoadIndirect(ILoadIndirectInstruction instruction) {}

    public void visitStoreIndirect(IStoreIndirectInstruction instruction) {}
  }

  /** @return true if the instruction can "fall through" to the following instruction */
  boolean isFallThrough();

  /**
   * @return an array containing the labels this instruction can branch to (not including the
   *     following instruction if this instruction 'falls through')
   */
  int[] getBranchTargets();

  /**
   * @return an Instruction equivalent to this one but with any branch labels updated by looking
   *     them up in the targetMap array
   */
  IInstruction redirectTargets(int[] targetMap);

  /** @return the number of values this instruction pops off the working stack */
  int getPoppedCount();

  /**
   * Computes the type of data pushed onto the stack, or null if none is pushed.
   *
   * @param poppedTypesToCheck the types of the data popped off the stack by this instruction; if
   *     poppedTypes is null, then we don't know the incoming stack types and the result of this
   *     method may be less accurate
   */
  String getPushedType(String[] poppedTypesToCheck);

  /**
   * @return the JVM word size of the value this instruction pushes onto the stack, or 0 if this
   *     instruction doesn't push anything onto the stack.
   */
  byte getPushedWordSize();

  /**
   * Apply a Visitor to this instruction. We invoke the appropriate Visitor method according to the
   * type of this instruction.
   */
  void visit(IInstruction.Visitor v);

  /** Subclasses must implement toString. */
  @Override
  String toString();

  /**
   * PEI == "Potentially excepting instruction"
   *
   * @return true iff this instruction might throw an exception
   */
  boolean isPEI();
}
