001 package serp.bytecode; 002 003 import java.io.*; 004 import java.util.*; 005 006 import serp.bytecode.visitor.*; 007 008 /** 009 * The <code>newarray</code> instruction, which is used to create new 010 * arrays of primitive types. 011 * 012 * @author Abe White 013 */ 014 public class NewArrayInstruction extends TypedInstruction { 015 private static final Class[][] _mappings = new Class[][] { 016 { void.class, int.class }, 017 { Object.class, int.class }, 018 }; 019 private int _code = -1; 020 021 NewArrayInstruction(Code owner) { 022 super(owner, Constants.NEWARRAY); 023 } 024 025 int getLength() { 026 return super.getLength() + 1; 027 } 028 029 public String getTypeName() { 030 switch (getTypeCode()) { 031 case Constants.ARRAY_BOOLEAN: 032 return boolean.class.getName(); 033 case Constants.ARRAY_CHAR: 034 return char.class.getName(); 035 case Constants.ARRAY_FLOAT: 036 return float.class.getName(); 037 case Constants.ARRAY_DOUBLE: 038 return double.class.getName(); 039 case Constants.ARRAY_BYTE: 040 return byte.class.getName(); 041 case Constants.ARRAY_SHORT: 042 return short.class.getName(); 043 case Constants.ARRAY_INT: 044 return int.class.getName(); 045 case Constants.ARRAY_LONG: 046 return long.class.getName(); 047 default: 048 return null; 049 } 050 } 051 052 public TypedInstruction setType(String type) { 053 type = mapType(type, _mappings, true); 054 if (type == null) 055 return setTypeCode(-1); 056 057 switch (type.charAt(0)) { 058 case 'b': 059 if (boolean.class.getName().equals(type)) 060 return setTypeCode(Constants.ARRAY_BOOLEAN); 061 return setTypeCode(Constants.ARRAY_BYTE); 062 case 'c': 063 return setTypeCode(Constants.ARRAY_CHAR); 064 case 'f': 065 return setTypeCode(Constants.ARRAY_FLOAT); 066 case 'd': 067 return setTypeCode(Constants.ARRAY_DOUBLE); 068 case 's': 069 return setTypeCode(Constants.ARRAY_SHORT); 070 case 'i': 071 return setTypeCode(Constants.ARRAY_INT); 072 case 'l': 073 return setTypeCode(Constants.ARRAY_LONG); 074 default: 075 throw new IllegalStateException(); 076 } 077 } 078 079 /** 080 * Return the array code used in the lowlevel bytecode, or -1 if unset. 081 */ 082 public int getTypeCode() { 083 return _code; 084 } 085 086 /** 087 * Set the array code used in the lowlevel bytecode. 088 * 089 * @return this instruction, for method chaining 090 */ 091 public NewArrayInstruction setTypeCode(int code) { 092 _code = code; 093 return this; 094 } 095 096 /** 097 * NewArray instructions are equal if the array type is the same, 098 * of if the array type of either is unset. 099 */ 100 public boolean equalsInstruction(Instruction other) { 101 if (this == other) 102 return true; 103 if (!(other instanceof NewArrayInstruction)) 104 return false; 105 106 NewArrayInstruction ins = (NewArrayInstruction) other; 107 int code = getTypeCode(); 108 int otherCode = ins.getTypeCode(); 109 return code == -1 || otherCode == -1 || code == otherCode; 110 } 111 112 public void acceptVisit(BCVisitor visit) { 113 visit.enterNewArrayInstruction(this); 114 visit.exitNewArrayInstruction(this); 115 } 116 117 void read(Instruction orig) { 118 super.read(orig); 119 _code = ((NewArrayInstruction) orig).getTypeCode(); 120 } 121 122 void read(DataInput in) throws IOException { 123 super.read(in); 124 _code = in.readUnsignedByte(); 125 } 126 127 void write(DataOutput out) throws IOException { 128 super.write(out); 129 out.writeByte(_code); 130 } 131 }