001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2006-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: /**
024: * A variable. This pseudo-type captures the name for globals,
025: * locals, parameters, fields, and bitfields. For the latter, it also
026: * captures the field width.
027: *
028: * @author Robert Grimm
029: * @version $Revision: 1.10 $
030: */
031: public class VariableT extends WrappedT {
032:
033: /** The variable kind. */
034: public static enum Kind {
035: /** A global variable. */
036: GLOBAL,
037: /** A local variable. */
038: LOCAL,
039: /** A parameter. */
040: PARAMETER,
041: /** A field. */
042: FIELD,
043: /** A bit-field. */
044: BITFIELD
045: }
046:
047: // =========================================================================
048:
049: /** The kind. */
050: private Kind kind;
051:
052: /** The name. */
053: private String name;
054:
055: /** The width for bitfields. */
056: private int width;
057:
058: /**
059: * Create a new variable type.
060: *
061: * @param template The type whose annotations to copy.
062: * @param type The type.
063: * @param kind The kind.
064: * @param name The name.
065: */
066: public VariableT(Type template, Type type, Kind kind, String name) {
067: super (template, type);
068: if (Kind.BITFIELD == kind) {
069: throw new IllegalArgumentException("Invalid kind " + kind);
070: }
071: this .kind = kind;
072: this .name = name;
073: this .width = -1;
074: }
075:
076: /**
077: * Create a new bit-field.
078: *
079: * @param template The type whose annotations to copy.
080: * @param type The type.
081: * @param name The name.
082: * @param width The width.
083: */
084: public VariableT(Type template, Type type, String name, int width) {
085: super (template, type);
086: if (0 > width) {
087: throw new IllegalArgumentException("Negative width "
088: + width);
089: }
090: this .kind = Kind.BITFIELD;
091: this .name = name;
092: this .width = width;
093: }
094:
095: public VariableT copy() {
096: return -1 == width ? new VariableT(this , getType().copy(),
097: kind, name) : new VariableT(this , getType().copy(),
098: name, width);
099: }
100:
101: public Type.Tag wtag() {
102: return Type.Tag.VARIABLE;
103: }
104:
105: public boolean isVariable() {
106: return true;
107: }
108:
109: public boolean hasVariable() {
110: return true;
111: }
112:
113: public VariableT toVariable() {
114: return this ;
115: }
116:
117: /**
118: * Determine whether this variable has the specified kind.
119: *
120: * @param kind The kind.
121: * @return <code>true</code> if this variable has the specified
122: * kind.
123: */
124: public boolean hasKind(Kind kind) {
125: return kind == this .kind;
126: }
127:
128: /**
129: * Get the kind.
130: *
131: * @return The kind.
132: */
133: public Kind getKind() {
134: return kind;
135: }
136:
137: /**
138: * Determine whether this variable has a name.
139: *
140: * @return <code>true</code> if this variable has a name.
141: */
142: public boolean hasName() {
143: return null != name;
144: }
145:
146: /**
147: * Determine whether this variable has the specified name.
148: *
149: * @param name The name.
150: * @return <code>true</code> if this variable has the name.
151: */
152: public boolean hasName(String name) {
153: return name.equals(this .name);
154: }
155:
156: /**
157: * Get the name.
158: *
159: * @return The name.
160: */
161: public String getName() {
162: return name;
163: }
164:
165: /**
166: * Determine whether this variable has a width.
167: *
168: * @return <code>true</code> if this variable has a width.
169: */
170: public boolean hasWidth() {
171: return -1 != width;
172: }
173:
174: /**
175: * Get this variable's width. If this variable is a bitfield, this
176: * method returns the bitfield's width. Otherwise, it returns -1.
177: *
178: * @return This variable's width.
179: */
180: public int getWidth() {
181: return width;
182: }
183:
184: public void write(Appendable out) throws IOException {
185: switch (kind) {
186: case GLOBAL:
187: out.append("global");
188: break;
189: case LOCAL:
190: out.append("local");
191: break;
192: case PARAMETER:
193: out.append("param");
194: break;
195: case FIELD:
196: out.append("field");
197: break;
198: case BITFIELD:
199: out.append("bitfield");
200: break;
201: }
202: out.append('(');
203: getType().write(out);
204: out.append(", ");
205: if (null != name) {
206: out.append(name);
207: } else {
208: out.append("<none>");
209: }
210: if (-1 != width) {
211: out.append(", ");
212: out.append(Integer.toString(width));
213: }
214: out.append(')');
215: }
216:
217: // =========================================================================
218:
219: /**
220: * Create a new global variable.
221: *
222: * @param type The type.
223: * @param name The name.
224: */
225: public static VariableT newGlobal(Type type, String name) {
226: return new VariableT(null, type, Kind.GLOBAL, name);
227: }
228:
229: /**
230: * Create a new local variable.
231: *
232: * @param type The type.
233: * @param name The name.
234: */
235: public static VariableT newLocal(Type type, String name) {
236: return new VariableT(null, type, Kind.LOCAL, name);
237: }
238:
239: /**
240: * Create a new parameter.
241: *
242: * @param type The type.
243: * @param name The name.
244: */
245: public static VariableT newParam(Type type, String name) {
246: return new VariableT(null, type, Kind.PARAMETER, name);
247: }
248:
249: /**
250: * Create a new field.
251: *
252: * @param type The type.
253: * @param name The name.
254: */
255: public static VariableT newField(Type type, String name) {
256: return new VariableT(null, type, Kind.FIELD, name);
257: }
258:
259: /**
260: * Create a new bitfield.
261: *
262: * @param type The type.
263: * @param name The name.
264: * @param width The width.
265: */
266: public static VariableT newBitfield(Type type, String name,
267: int width) {
268: return new VariableT(null, type, name, width);
269: }
270:
271: }
|