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.util.List;
022:
023: import xtc.util.Nonce;
024:
025: /**
026: * The superclass of struct and union types.
027: *
028: * @author Robert Grimm
029: * @version $Revision: 1.40 $
030: */
031: public abstract class StructOrUnionT extends DerivedT implements Tagged {
032:
033: /** The nonce. */
034: protected final Nonce nonce;
035:
036: /** The name. */
037: protected final String name;
038:
039: /** The list of members represents as {@link VariableT}. */
040: protected List<VariableT> members;
041:
042: /**
043: * Create a new struct or union type.
044: *
045: * @param template The type whose annotations to copy.
046: * @param nonce The nonce.
047: * @param name The name.
048: * @param members The members.
049: * @throws NullPointerException Signals a null name.
050: */
051: public StructOrUnionT(Type template, Nonce nonce, String name,
052: List<VariableT> members) {
053: super (template);
054: if (null == name)
055: throw new NullPointerException("Null name");
056: this .nonce = nonce;
057: this .name = name;
058: this .members = members;
059: }
060:
061: /**
062: * Seal this struct or union. If this struct or union is
063: * incomplete, i.e., does not have any members, invocations to this
064: * method have no effect.
065: */
066: public Type seal() {
067: if (null != members) {
068: if (!isSealed()) {
069: super .seal();
070: members = Type.seal(members);
071: }
072: }
073: return this ;
074: }
075:
076: public boolean hasTagged() {
077: return true;
078: }
079:
080: public Tagged toTagged() {
081: return this ;
082: }
083:
084: public Nonce getNonce() {
085: return nonce;
086: }
087:
088: public boolean isUnnamed() {
089: return name.startsWith("tag(");
090: }
091:
092: public boolean hasName(String name) {
093: return name.equals(this .name);
094: }
095:
096: public String getName() {
097: return name;
098: }
099:
100: public Type lookup(String name) {
101: for (VariableT member : members) {
102: if (member.hasName(name))
103: return member;
104:
105: if ((!member.hasName()) && (!member.hasWidth())) {
106: // The member is an unnamed struct or union.
107: Type nested = ((StructOrUnionT) member.resolve())
108: .lookup(name);
109: if (!nested.isError())
110: return nested;
111: }
112: }
113: return ErrorT.TYPE;
114: }
115:
116: public int getMemberCount() {
117: if (null == members) {
118: return -1;
119: } else {
120: int count = 0;
121: for (VariableT member : members) {
122: // If the member has a name, it counts. If the member does
123: // not have a name and does not have a width, it is an
124: // unnamed struct/union and counts.
125: if (member.hasName() || (!member.hasWidth()))
126: count++;
127: }
128: return count;
129: }
130: }
131:
132: public Type getMember(int index) {
133: int count = -1;
134: for (VariableT member : members) {
135: if (member.hasName() || (!member.hasWidth())) {
136: count++;
137: if (index == count)
138: return member;
139: }
140: }
141: throw new IndexOutOfBoundsException("Index: " + index
142: + ", Size: " + (count + 1));
143: }
144:
145: public List<VariableT> getMembers() {
146: return members;
147: }
148:
149: /**
150: * Set the members.
151: *
152: * @param members The members.
153: * @throws IllegalStateException Signals that this type is sealed.
154: */
155: public void setMembers(List<VariableT> members) {
156: checkNotSealed();
157: this .members = members;
158: }
159:
160: public int hashCode() {
161: return name.hashCode();
162: }
163:
164: /**
165: * Determine whether this type equals the specified object. A
166: * struct or union equals the specified object if the specified
167: * object is a struct or union with the same nonce.
168: *
169: * @param o The object.
170: * @return <code>true</code> if this type equals the object.
171: */
172: public boolean equals(Object o) {
173: if (!(o instanceof Type))
174: return false;
175: Type t = (Type) o;
176: return t.hasTagged() && (nonce == t.toTagged().getNonce());
177: }
178:
179: }
|