Source code: com/techtrader/modules/tools/bytecode/ReturnInstruction.java
1 package com.techtrader.modules.tools.bytecode;
2
3
4 import java.util.Map;
5 import java.util.HashMap;
6 import java.io.IOException;
7 import java.io.DataInput;
8 import java.io.DataOutput;
9
10 import com.techtrader.modules.tools.bytecode.visitor.BCVisitor;
11
12
13 /**
14 * Represents a return instruction.
15 *
16 * @author Abe White
17 */
18 public class ReturnInstruction
19 extends Instruction
20 {
21 protected static final Map _typeNames = new HashMap ();
22 static
23 {
24 _typeNames.put ("void", void.class);
25 _typeNames.put ("int", int.class);
26 _typeNames.put ("long", long.class);
27 _typeNames.put ("float", float.class);
28 _typeNames.put ("double", double.class);
29 _typeNames.put ("boolean", int.class);
30 _typeNames.put ("byte", int.class);
31 _typeNames.put ("char", int.class);
32 _typeNames.put ("short", int.class);
33 }
34
35 private Class _type = null;
36
37
38 protected ReturnInstruction (Code owner)
39 {
40 super (owner);
41 }
42
43
44 protected ReturnInstruction (Code owner, int opcode, Class type)
45 {
46 super (owner);
47 _opcode = opcode;
48 _type = type;
49 }
50
51
52 /**
53 * Get the type to return; this is one of:
54 * int, float, double, long, void, or Object.class.
55 * If the type has not been set, this method will return null.
56 */
57 public Class getType ()
58 {
59 return _type;
60 }
61
62
63 /**
64 * Get the type to return; this is one of:
65 * int, float, double, long, void, or java.lang.Object.
66 * If the type has not been set, this method will return null.
67 */
68 public String getTypeName ()
69 {
70 if (_type == null)
71 return null;
72
73 return _type.getName ();
74 }
75
76
77 /**
78 * Set the type to rturn; Object types other than Object.class
79 * will be demoted to Object.class, and primitives that have no direct
80 * support (boolean, char, short, byte) will be converted to int.class.
81 *
82 * @return this Instruction, for method chaining
83 */
84 public ReturnInstruction setType (Class type)
85 {
86 if (Object.class.isAssignableFrom (type))
87 _type = Object.class;
88 else if (boolean.class.equals (type) || char.class.equals (type)
89 || byte.class.equals (type) || short.class.equals (type))
90 _type = int.class;
91 else
92 _type = type;
93
94 calculateOpCode ();
95 return this;
96 }
97
98
99 /**
100 * Set the type to load by name.
101 *
102 * @return this Instruction, for method chaining
103 *
104 * @see #setType(java.lang.Class)
105 */
106 public ReturnInstruction setTypeName (String name)
107 {
108 _type = (Class) _typeNames.get (name);
109 if (_type == null && name != null)
110 _type = Object.class;
111
112 calculateOpCode ();
113 return this;
114 }
115
116
117 /**
118 * Two return instructions are equal if the types they
119 * reference are equal or if either unset.
120 */
121 public boolean equals (Object other)
122 {
123 if (this == other)
124 return true;
125 if (!(other instanceof ReturnInstruction))
126 return false;
127
128 ReturnInstruction ins = (ReturnInstruction) other;
129
130 return (_type == null || ins._type == null
131 || _type.equals (ins._type));
132 }
133
134
135 public int getStackChange ()
136 {
137 switch (_opcode)
138 {
139 case RETURN:
140 return 0;
141 case LRETURN:
142 case DRETURN:
143 return -2;
144 default:
145 return -1;
146 }
147 }
148
149
150 protected void copy (Instruction orig)
151 {
152 super.copy (orig);
153 _type = ((ReturnInstruction) orig)._type;
154 }
155
156
157 private void calculateOpCode ()
158 {
159 if (void.class.equals (_type))
160 _opcode = RETURN;
161 else
162 _opcode = IRETURN + _opcodeTypes.indexOf (_type);
163 }
164
165
166 public void acceptVisit (BCVisitor visit)
167 {
168 visit.enterReturnInstruction (this);
169 visit.exitReturnInstruction (this);
170 }
171 }