001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2005-2007 Robert Grimm
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * version 2 as published by the Free Software Foundation.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
017: * USA.
018: */
019: package xtc.type;
020:
021: import java.io.IOException;
022:
023: import java.util.List;
024:
025: import xtc.util.Nonce;
026:
027: /**
028: * An enumerated type. Note that the list of members for an
029: * enumerated type is the list of enumerators.
030: *
031: * @author Robert Grimm
032: * @version $Revision: 1.40 $
033: */
034: public class EnumT extends WrappedT implements Tagged {
035:
036: /** The nonce. */
037: private final Nonce nonce;
038:
039: /** The name. */
040: private final String name;
041:
042: /** The list of {@link EnumeratorT enumerators}. */
043: private List<EnumeratorT> enumerators;
044:
045: /**
046: * Create a new, incomplete enum type. The newly created enum type
047: * has a fresh nonce and {@link ErrorT#TYPE} as its type.
048: *
049: * @param name The name.
050: * @throws NullPointerException Signals a null name.
051: */
052: public EnumT(String name) {
053: this (null, ErrorT.TYPE, Nonce.create(), name, null);
054: }
055:
056: /**
057: * Create a new enum type. The newly created enum type has a fresh
058: * nonce.
059: *
060: * @param type The underlying type.
061: * @param name The name.
062: * @param enumerators The enumerators.
063: * @throws NullPointerException Signals a null name.
064: */
065: public EnumT(Type type, String name, List<EnumeratorT> enumerators) {
066: this (null, type, Nonce.create(), name, enumerators);
067: }
068:
069: /**
070: * Create a new enum type.
071: *
072: * @param template The type whose annotations to copy.
073: * @param type The underlying type.
074: * @param nonce The nonce.
075: * @param name The name.
076: * @param enumerators The enumerators.
077: * @throws NullPointerException Signals a null name.
078: */
079: public EnumT(Type template, Type type, Nonce nonce, String name,
080: List<EnumeratorT> enumerators) {
081: super (template, type);
082: if (null == name)
083: throw new NullPointerException("Null name");
084: this .nonce = nonce;
085: this .name = name;
086: this .enumerators = enumerators;
087: }
088:
089: public EnumT copy() {
090: return new EnumT(this , getType().copy(), nonce, name,
091: copy(enumerators));
092: }
093:
094: /**
095: * Seal this enum. If this enum is incomplete, i.e., does not have
096: * any enumerators, invocations to this method have no effect.
097: */
098: public Type seal() {
099: if (null != enumerators) {
100: if (!isSealed()) {
101: super .seal();
102: enumerators = Type.seal(enumerators);
103: }
104: }
105: return this ;
106: }
107:
108: public Type.Tag wtag() {
109: return Type.Tag.ENUM;
110: }
111:
112: public boolean isEnum() {
113: return true;
114: }
115:
116: public boolean hasEnum() {
117: return true;
118: }
119:
120: public EnumT toEnum() {
121: return this ;
122: }
123:
124: public boolean hasTagged() {
125: return true;
126: }
127:
128: public Tagged toTagged() {
129: return this ;
130: }
131:
132: /**
133: * Set the type. This method {@link EnumeratorT#setType(Type) sets}
134: * the enumerators' types to the specified type, which should be an
135: * {@link IntegerT integer}. When modifying an incomplete type,
136: * this method should be called after the appropriate call to {@link
137: * #setMembers(List)}.
138: *
139: * @param type The type.
140: * @throws IllegalStateException Signals that this type is sealed.
141: */
142: public void setType(Type type) {
143: super .setType(type);
144: for (EnumeratorT e : enumerators)
145: e.setType(type);
146: }
147:
148: public Nonce getNonce() {
149: return nonce;
150: }
151:
152: public boolean isUnnamed() {
153: return name.startsWith("tag(");
154: }
155:
156: public boolean hasName(String name) {
157: return name.equals(this .name);
158: }
159:
160: public String getName() {
161: return name;
162: }
163:
164: public Type lookup(String name) {
165: for (EnumeratorT e : enumerators) {
166: if (e.hasName(name))
167: return e;
168: }
169: return ErrorT.TYPE;
170: }
171:
172: public int getMemberCount() {
173: return null == enumerators ? -1 : enumerators.size();
174: }
175:
176: public EnumeratorT getMember(int index) {
177: return enumerators.get(index);
178: }
179:
180: public List<EnumeratorT> getMembers() {
181: return enumerators;
182: }
183:
184: /**
185: * Set the list of {@link EnumeratorT enumerators}. This method
186: * does <em>not</em> change the type of the enumerators.
187: *
188: * @param enumerators The enumerators.
189: * @throws IllegalStateException Signals that this type is sealed.
190: */
191: public void setMembers(List<EnumeratorT> enumerators) {
192: checkNotSealed();
193: this .enumerators = enumerators;
194: }
195:
196: public int hashCode() {
197: return name.hashCode();
198: }
199:
200: /**
201: * Determine whether this type equals the specified object. This
202: * enum type equals the specified object if the object is an enum
203: * type with the same nonce.
204: *
205: * @param o The object.
206: * @return <code>true</code> if this type equals the object.
207: */
208: public boolean equals(Object o) {
209: if (!(o instanceof Type))
210: return false;
211: Type t = (Type) o;
212: return t.hasTagged() && (nonce == t.toTagged().getNonce());
213: }
214:
215: public void write(Appendable out) throws IOException {
216: out.append("enum ");
217: out.append(name);
218: }
219:
220: }
|