1 package serp.bytecode;
2
3 import java.util.*;
4
5 import serp.bytecode.lowlevel.*;
6 import serp.util.*;
7
8 /***
9 * Any typed instruction.
10 *
11 * @author Abe White
12 */
13 public abstract class TypedInstruction extends Instruction {
14 private static final Set _opcodeTypes = new HashSet();
15 static {
16 _opcodeTypes.add(int.class.getName());
17 _opcodeTypes.add(long.class.getName());
18 _opcodeTypes.add(float.class.getName());
19 _opcodeTypes.add(double.class.getName());
20 _opcodeTypes.add(Object.class.getName());
21 _opcodeTypes.add(byte.class.getName());
22 _opcodeTypes.add(char.class.getName());
23 _opcodeTypes.add(short.class.getName());
24 _opcodeTypes.add(boolean.class.getName());
25 _opcodeTypes.add(void.class.getName());
26 }
27
28 TypedInstruction(Code owner) {
29 super(owner);
30 }
31
32 TypedInstruction(Code owner, int opcode) {
33 super(owner, opcode);
34 }
35
36 /***
37 * Return the type for the given name. Takes into account
38 * the given mappings and the demote flag.
39 *
40 * @param mappings mappings of one type to another; for example,
41 * array instruction treat booleans as ints, so
42 * to reflect that there should be an index x of the
43 * array such that mappings[x][0] = boolean.class and
44 * mappings[x][1] = int.class; may be null if no special mappings are needed
45 * @param demote if true, all object types will be demoted to Object.class
46 */
47 String mapType(String type, Class[][] mappings, boolean demote) {
48 if (type == null)
49 return null;
50
51 type = getProject().getNameCache().getExternalForm(type, false);
52 if (!_opcodeTypes.contains(type) && demote)
53 type = Object.class.getName();
54
55 if (mappings != null)
56 for (int i = 0; i < mappings.length; i++)
57 if (mappings[i][0].getName().equals(type))
58 type = mappings[i][1].getName();
59 return type;
60 }
61
62 /***
63 * Return the type name for this instruction.
64 * If the type has not been set, this method will return null.
65 */
66 public abstract String getTypeName();
67
68 /***
69 * Return the type for this instruction.
70 * If the type has not been set, this method will return null.
71 */
72 public Class getType() {
73 String type = getTypeName();
74 if (type == null)
75 return null;
76 return Strings.toClass(type, getClassLoader());
77 }
78
79 /***
80 * Return the type for this instruction.
81 * If the type has not been set, this method will return null.
82 */
83 public BCClass getTypeBC() {
84 String type = getTypeName();
85 if (type == null)
86 return null;
87 return getProject().loadClass(type, getClassLoader());
88 }
89
90 /***
91 * Set the type of this instruction. Types that have no direct
92 * support will be converted accordingly.
93 *
94 * @return this instruction, for method chaining
95 */
96 public abstract TypedInstruction setType(String type);
97
98 /***
99 * Set the type of this instruction. Types that have no direct
100 * support will be converted accordingly.
101 *
102 * @return this instruction, for method chaining
103 */
104 public TypedInstruction setType(Class type) {
105 if (type == null)
106 return setType((String) null);
107 return setType(type.getName());
108 }
109
110 /***
111 * Set the type of this instruction. Types that have no direct
112 * support will be converted accordingly.
113 *
114 * @return this instruction, for method chaining
115 */
116 public TypedInstruction setType(BCClass type) {
117 if (type == null)
118 return setType((String) null);
119 return setType(type.getName());
120 }
121 }