/*
* xtc - The eXTensible Compiler
* Copyright (C) 2006-2007 Robert Grimm
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package xtc.type;
import java.io.IOException;
/**
* A variable. This pseudo-type captures the name for globals,
* locals, parameters, fields, and bitfields. For the latter, it also
* captures the field width.
*
* @author Robert Grimm
* @version $Revision: 1.10 $
*/
public class VariableT extends WrappedT {
/** The variable kind. */
public static enum Kind {
/** A global variable. */
GLOBAL,
/** A local variable. */
LOCAL,
/** A parameter. */
PARAMETER,
/** A field. */
FIELD,
/** A bit-field. */
BITFIELD
}
// =========================================================================
/** The kind. */
private Kind kind;
/** The name. */
private String name;
/** The width for bitfields. */
private int width;
/**
* Create a new variable type.
*
* @param template The type whose annotations to copy.
* @param type The type.
* @param kind The kind.
* @param name The name.
*/
public VariableT(Type template, Type type, Kind kind, String name) {
super(template, type);
if (Kind.BITFIELD == kind) {
throw new IllegalArgumentException("Invalid kind " + kind);
}
this.kind = kind;
this.name = name;
this.width = -1;
}
/**
* Create a new bit-field.
*
* @param template The type whose annotations to copy.
* @param type The type.
* @param name The name.
* @param width The width.
*/
public VariableT(Type template, Type type, String name, int width) {
super(template, type);
if (0 > width) {
throw new IllegalArgumentException("Negative width " + width);
}
this.kind = Kind.BITFIELD;
this.name = name;
this.width = width;
}
public VariableT copy() {
return -1 == width ?
new VariableT(this, getType().copy(), kind, name)
: new VariableT(this, getType().copy(), name, width);
}
public Type.Tag wtag() {
return Type.Tag.VARIABLE;
}
public boolean isVariable() {
return true;
}
public boolean hasVariable() {
return true;
}
public VariableT toVariable() {
return this;
}
/**
* Determine whether this variable has the specified kind.
*
* @param kind The kind.
* @return <code>true</code> if this variable has the specified
* kind.
*/
public boolean hasKind(Kind kind) {
return kind == this.kind;
}
/**
* Get the kind.
*
* @return The kind.
*/
public Kind getKind() {
return kind;
}
/**
* Determine whether this variable has a name.
*
* @return <code>true</code> if this variable has a name.
*/
public boolean hasName() {
return null != name;
}
/**
* Determine whether this variable has the specified name.
*
* @param name The name.
* @return <code>true</code> if this variable has the name.
*/
public boolean hasName(String name) {
return name.equals(this.name);
}
/**
* Get the name.
*
* @return The name.
*/
public String getName() {
return name;
}
/**
* Determine whether this variable has a width.
*
* @return <code>true</code> if this variable has a width.
*/
public boolean hasWidth() {
return -1 != width;
}
/**
* Get this variable's width. If this variable is a bitfield, this
* method returns the bitfield's width. Otherwise, it returns -1.
*
* @return This variable's width.
*/
public int getWidth() {
return width;
}
public void write(Appendable out) throws IOException {
switch (kind) {
case GLOBAL:
out.append("global"); break;
case LOCAL:
out.append("local"); break;
case PARAMETER:
out.append("param"); break;
case FIELD:
out.append("field"); break;
case BITFIELD:
out.append("bitfield"); break;
}
out.append('(');
getType().write(out);
out.append(", ");
if (null != name) {
out.append(name);
} else {
out.append("<none>");
}
if (-1 != width) {
out.append(", ");
out.append(Integer.toString(width));
}
out.append(')');
}
// =========================================================================
/**
* Create a new global variable.
*
* @param type The type.
* @param name The name.
*/
public static VariableT newGlobal(Type type, String name) {
return new VariableT(null, type, Kind.GLOBAL, name);
}
/**
* Create a new local variable.
*
* @param type The type.
* @param name The name.
*/
public static VariableT newLocal(Type type, String name) {
return new VariableT(null, type, Kind.LOCAL, name);
}
/**
* Create a new parameter.
*
* @param type The type.
* @param name The name.
*/
public static VariableT newParam(Type type, String name) {
return new VariableT(null, type, Kind.PARAMETER, name);
}
/**
* Create a new field.
*
* @param type The type.
* @param name The name.
*/
public static VariableT newField(Type type, String name) {
return new VariableT(null, type, Kind.FIELD, name);
}
/**
* Create a new bitfield.
*
* @param type The type.
* @param name The name.
* @param width The width.
*/
public static VariableT newBitfield(Type type, String name, int width) {
return new VariableT(null, type, name, width);
}
}