001package daikon.chicory;
002
003import java.util.EnumSet;
004import org.checkerframework.dataflow.qual.Pure;
005
006/**
007 * The ParameterInfo class is a subtype of DaikonVariableInfo used for variable types which are
008 * arguments to procedures.
009 *
010 * <p>This class takes "precedence" over when a seeming conflict could arise. For instance,
011 * consider: public static sort(int array[]). Is the "array" parameter represented as an
012 * ParameterInfo object or an ArrayInfo object? Because ParameterInfo takes precedence, it is the
013 * former. This makes sense because the arrays are really treated as hash codes at the first level,
014 * so such a parameter needs no array-specific processing (at this level of the tree at least).
015 */
016public class ParameterInfo extends DaikonVariableInfo {
017  /**
018   * The argument number for this parameter. For instance, consider the method void x(int a, double
019   * b, Object c). Then a, b, and c have argument numbers 0, 1 and 2 respectively.
020   */
021  private final int argNum;
022
023  /**
024   * Offset of this parameter in the local table. This is similar to the argument number except that
025   * doubles and longs take up two slots each.
026   */
027  private final int param_offset;
028
029  /** Argument type. */
030  private final Class<?> argType;
031
032  /** True if this parameter is of a primitive type. */
033  boolean isPrimitive;
034
035  /**
036   * Constructs an ParameterInfo object with the specified name.
037   *
038   * @param theName the variable name (used in the declaration)
039   */
040  public ParameterInfo(String theName, int theArgNum, Class<?> argType, int param_offset) {
041    super(
042        theName,
043        stdClassName(argType) + DaikonVariableInfo.isParamString,
044        getRepName(argType, false));
045
046    argNum = theArgNum;
047    this.param_offset = param_offset;
048    this.argType = argType;
049    this.isPrimitive = argType.isPrimitive();
050  }
051
052  /**
053   * Constructs a PamterInfo object with the name/type specified for this the specified argument
054   * number in mi.
055   */
056  public ParameterInfo(MethodInfo mi, int theArgNum, int param_offset) {
057    this(mi.arg_names[theArgNum], theArgNum, mi.arg_types[theArgNum], param_offset);
058  }
059
060  /** Returns the argument number for this parameter. */
061  public int getArgNum() {
062    return argNum;
063  }
064
065  /** Returns the offset in the local table for this parameter. */
066  public int get_param_offset() {
067    return param_offset;
068  }
069
070  @Override
071  public Object getMyValFromParentVal(Object value) {
072    // a parameter has no parent value
073    throw new RuntimeException("Parameters have no parent value");
074  }
075
076  public Class<?> getType() {
077    return argType;
078  }
079
080  /** Returns whether or not this parameter is a primitive type. */
081  @Pure
082  public boolean isPrimitive() {
083    return isPrimitive;
084  }
085
086  /** Parameters are not enclosed in other variable, so they are of kind VARIABLE. */
087  @Override
088  public VarKind get_var_kind() {
089    return VarKind.VARIABLE;
090  }
091
092  /** Add IS_PARM to list of variable flags. */
093  @Override
094  public EnumSet<VarFlags> get_var_flags() {
095    // System.out.printf("%s is a parameter%n", this);
096    EnumSet<VarFlags> var_flags = super.get_var_flags();
097    var_flags.add(VarFlags.IS_PARAM);
098    return var_flags;
099  }
100}