001: // Copyright (c) 1997 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.bytecode;
005:
006: public class ArrayType extends ObjectType {
007: public Type elements;
008:
009: /**
010: * @deprecated Replaced by {@link #make(gnu.bytecode.Type)}
011: */
012: public ArrayType(Type elements) {
013: this (elements, elements.getName() + "[]");
014: }
015:
016: //private ?
017: ArrayType(Type elements, String name) {
018: this _name = name;
019: setSignature("[" + elements.getSignature());
020: this .elements = elements;
021: }
022:
023: public final boolean isArray() {
024: return true;
025: }
026:
027: public Type getImplementationType() {
028: Type eltype = elements.getImplementationType();
029: return elements == eltype ? this : make(eltype);
030: }
031:
032: /** Find or create an ArrayType for the specified element type. */
033: public static ArrayType make(Type elements) {
034: String name = elements.getName() + "[]";
035: ArrayType type = (ArrayType) Type.lookupType(name);
036: if (type == null //|| type.elements != elements
037: ) {
038: type = new ArrayType(elements, name);
039: mapNameToType.put(name, type);
040: }
041: return type;
042: }
043:
044: public Type getComponentType() {
045: return elements;
046: }
047:
048: public String getInternalName() {
049: return getSignature();
050: }
051:
052: /** Return true if this is a "subtype" of other. */
053: public boolean isSubtype(Type other) {
054: if (!(other instanceof ArrayType))
055: return false;
056:
057: Type otherElements = ((ArrayType) other).elements;
058:
059: return elements.isSubtype(otherElements);
060: }
061:
062: public int compare(Type other) {
063: if (other == nullType)
064: return 1;
065: if (other instanceof ArrayType)
066: return elements.compare(((ArrayType) other).elements);
067: else if (other.getName().equals("java.lang.Object"))
068: return -1;
069: else
070: return -3;
071: }
072:
073: /** @return true if values of this type can be assigned to other
074: <b>without widening nor conversion</b>.
075: */
076: public boolean isAssignableTo(Type other) {
077: if (other == pointer_type || this == other)
078: return true;
079:
080: if (!(other instanceof ArrayType))
081: return false;
082:
083: ArrayType o = (ArrayType) other;
084: return elements.getSignature()
085: .equals(o.elements.getSignature());
086: }
087:
088: public void emitCoerceFrom(Type fromType, CodeAttr code) {
089: if (!(fromType instanceof ArrayType)) {
090: super .emitCoerceFrom(fromType, code);
091: return;
092: }
093:
094: Type from = ((ArrayType) fromType).elements;
095:
096: if (elements == from)
097: // Nothing to do
098: return;
099:
100: if (!(elements instanceof PrimType && from instanceof PrimType))
101: // Java arrays are covariant for reference types. Nothing to do.
102: return;
103:
104: /*
105: Create a new array, then convert all the elements
106: and put them in the new array.
107: */
108:
109: Scope scope = code.pushScope();
110:
111: Variable old = code.addLocal(fromType);
112: code.emitStore(old);
113:
114: Variable newArray = code.addLocal(this );
115: code.emitLoad(old);
116: code.emitArrayLength();
117: code.emitNewArray(elements, 1);
118: code.emitStore(newArray);
119:
120: // Counter to go though each element.
121: Variable elem = code.addLocal(Type.int_type);
122: code.emitPushInt(0);
123: code.emitStore(elem);
124:
125: Label test = new Label(code);
126: Label copy = new Label(code);
127:
128: code.emitGoto(test);
129:
130: copy.define(code);
131:
132: // Prepare the store in the new array.
133: code.emitLoad(newArray);
134: code.emitLoad(elem);
135:
136: // Load an element from the source array, and convert it.
137: code.emitLoad(old);
138: code.emitLoad(elem);
139: code.emitArrayLoad(from);
140: code.emitConvert(from, elements);
141:
142: code.emitArrayStore(elements);
143:
144: code.emitInc(elem, (short) 1);
145:
146: // Check if there are more elements to copy.
147: test.define(code);
148: code.emitLoad(elem);
149: code.emitLoad(old);
150: code.emitArrayLength();
151: code.emitGotoIfLt(copy);
152:
153: // The new array is the result.
154: code.emitLoad(newArray);
155: code.popScope();
156: }
157: }
|