/* Soot - a J*va Optimization Framework * Copyright (C) 1997-1999 Raja Vallee-Rai * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* * Modified by the Sable Research Group and others 1997-1999. * See the 'credits' file distributed with Soot for the complete list of * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot) */ package soot; import soot.util.*; /** * A class that models Java's array types. ArrayTypes are parametrized by a Type and * and an integer representing the array's dimension count.. * Two ArrayType are 'equal' if they are parametrized equally. * * * */ public class ArrayType extends RefLikeType { /** * baseType can be any type except for an array type, null and void * * What is the base type of the array? That is, for an array of type * A[][][], how do I find out what the A is? The accepted way of * doing this has always been to look at the public field baseType * in ArrayType, ever since the very beginning of Soot. */ public final Type baseType; /** dimension count for the array type*/ public final int numDimensions; private ArrayType(Type baseType, int numDimensions) { if( !( baseType instanceof PrimType || baseType instanceof RefType ) ) throw new RuntimeException( "oops" ); if( numDimensions < 1 ) throw new RuntimeException( "attempt to create array with "+numDimensions+" dimensions" ); this.baseType = baseType; this.numDimensions = numDimensions; } /** * Creates an ArrayType parametrized by a given Type and dimension count. * @param baseType a Type to parametrize the ArrayType * @param numDimensions the dimension count to parametrize the ArrayType. * @return an ArrayType parametrized accrodingly. */ public static ArrayType v(Type baseType, int numDimensions) { if( numDimensions < 1 ) throw new RuntimeException( "attempt to create array with "+numDimensions+" dimensions" ); ArrayType ret; Type elementType; if( numDimensions == 1 ) { elementType = baseType; } else { elementType = ArrayType.v( baseType, numDimensions-1 ); } ret = elementType.getArrayType(); if( ret == null ) { ret = new ArrayType(baseType, numDimensions); elementType.setArrayType( ret ); } return ret; } /** * Two ArrayType are 'equal' if they are parametrized identically. * (ie have same Type and dimension count. * @param t object to test for equality * @return true if t is an ArrayType and is parametrized identically to this. */ public boolean equals(Object t) { return t == this; /* if(t instanceof ArrayType) { ArrayType arrayType = (ArrayType) t; return this.numDimensions == arrayType.numDimensions && this.baseType.equals(arrayType.baseType); } else return false; */ } public void toString(UnitPrinter up) { up.type( baseType ); for(int i = 0; i < numDimensions; i++) up.literal("[]"); } public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(baseType.toString()); for(int i = 0; i < numDimensions; i++) buffer.append("[]"); return buffer.toString(); } public int hashCode() { return baseType.hashCode() + 0x432E0341 * numDimensions; } public void apply(Switch sw) { ((TypeSwitch) sw).caseArrayType(this); } /** * If I have a variable x of declared type t, what is a good * declared type for the expression ((Object[]) x)[i]? The * getArrayElementType() method in RefLikeType was introduced to * answer this question for all classes implementing RefLikeType. If * t is an array, then the answer is the same as getElementType(). * But t could also be Object, Serializable, or Cloneable, which can * all hold any array, so then the answer is Object. */ public Type getArrayElementType() { return getElementType(); } /** * If I get an element of the array, what will be its type? That * is, if I have an array a of type A[][][], what is the type of * a[] (it's A[][])? The getElementType() method in ArrayType was * introduced to answer this question. */ public Type getElementType() { if( numDimensions > 1 ) { return ArrayType.v( baseType, numDimensions-1 ); } else { return baseType; } } public ArrayType makeArrayType() { return ArrayType.v( baseType, numDimensions+1 ); } }