001package serp.bytecode;
002
003import java.util.*;
004
005import serp.bytecode.lowlevel.*;
006import serp.util.*;
007
008/**
009 * Any typed instruction.
010 *
011 * @author Abe White
012 */
013public abstract class TypedInstruction extends Instruction {
014    private static final Set _opcodeTypes = new HashSet();
015    static {
016        _opcodeTypes.add(int.class.getName());
017        _opcodeTypes.add(long.class.getName());
018        _opcodeTypes.add(float.class.getName());
019        _opcodeTypes.add(double.class.getName());
020        _opcodeTypes.add(Object.class.getName());
021        _opcodeTypes.add(byte.class.getName());
022        _opcodeTypes.add(char.class.getName());
023        _opcodeTypes.add(short.class.getName());
024        _opcodeTypes.add(boolean.class.getName());
025        _opcodeTypes.add(void.class.getName());
026    }
027
028    TypedInstruction(Code owner) {
029        super(owner);
030    }
031
032    TypedInstruction(Code owner, int opcode) {
033        super(owner, opcode);
034    }
035
036    /**
037     * Return the type for the given name. Takes into account
038     * the given mappings and the demote flag.
039     *
040     * @param mappings mappings of one type to another; for example,
041     * array instruction treat booleans as ints, so
042     * to reflect that there should be an index x of the
043     * array such that mappings[x][0] = boolean.class and
044     * mappings[x][1] = int.class; may be null if no special mappings are needed
045     * @param demote if true, all object types will be demoted to Object.class
046     */
047    String mapType(String type, Class[][] mappings, boolean demote) {
048        if (type == null)
049            return null;
050
051        type = getProject().getNameCache().getExternalForm(type, false);
052        if (!_opcodeTypes.contains(type) && demote)
053            type = Object.class.getName();
054
055        if (mappings != null)
056            for (int i = 0; i < mappings.length; i++)
057                if (mappings[i][0].getName().equals(type))
058                    type = mappings[i][1].getName();
059        return type;
060    }
061
062    /**
063     * Return the type name for this instruction.
064     * If the type has not been set, this method will return null.
065     */
066    public abstract String getTypeName();
067
068    /**
069     * Return the type for this instruction.
070     * If the type has not been set, this method will return null.
071     */
072    public Class getType() {
073        String type = getTypeName();
074        if (type == null)
075            return null;
076        return Strings.toClass(type, getClassLoader());
077    }
078
079    /**
080     * Return the type for this instruction.
081     * If the type has not been set, this method will return null.
082     */
083    public BCClass getTypeBC() {
084        String type = getTypeName();
085        if (type == null)
086            return null;
087        return getProject().loadClass(type, getClassLoader());
088    }
089
090    /**
091     * Set the type of this instruction. Types that have no direct
092     * support will be converted accordingly.
093     *
094     * @return this instruction, for method chaining
095     */
096    public abstract TypedInstruction setType(String type);
097
098    /**
099     * 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}