View Javadoc

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 }