001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 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 type parameter. When a type is parameterized, all occurrences of
025: * the same parameter should also be the same instance of this class.
026: * Furthermore, the type should be wrapped in a {@link ParameterizedT}
027: * listing all parameters. Instantiation of a parameterized type does
028: * not require replacing all parameters, but rather should be
029: * implemented by wrapping the paramterized type in a {@link
030: * InstantiatedT} listing all arguments. To support efficient
031: * unification, this class implements union/find operations with path
032: * compression through the {@link #bind(Type)} and {@link #lookup()}
033: * operations.
034: *
035: * @author Robert Grimm
036: * @version $Revision: 1.3 $
037: */
038: public class Parameter extends Type {
039:
040: /** The name. */
041: private final String name;
042:
043: /** The binding. */
044: private Type binding;
045:
046: /**
047: * Create a new parameter.
048: *
049: * @param name The name.
050: */
051: public Parameter(String name) {
052: this .name = name;
053: }
054:
055: /**
056: * Create a new parameter.
057: *
058: * @param template The type whose annotations to copy.
059: * @param name The name.
060: */
061: public Parameter(Type template, String name) {
062: super (template);
063: this .name = name;
064: }
065:
066: public Parameter copy() {
067: return new Parameter(this , name);
068: }
069:
070: public Type.Tag tag() {
071: return Type.Tag.PARAMETER;
072: }
073:
074: public boolean isParameter() {
075: return true;
076: }
077:
078: public Parameter toParameter() {
079: return this ;
080: }
081:
082: /**
083: * Get the name.
084: *
085: * @return The name.
086: */
087: public String getName() {
088: return name;
089: }
090:
091: /**
092: * Bind this parameter to the specified type.
093: *
094: * @param type The type.
095: * @throws IllegalStateException Signals that this parameter is
096: * sealed or already bound.
097: */
098: public void bind(Type type) {
099: checkNotSealed();
100: if (null != binding) {
101: throw new IllegalStateException("Parameter already bound");
102: }
103:
104: binding = type;
105: if (binding.isParameter())
106: binding = binding.toParameter().lookup();
107: }
108:
109: /**
110: * Look up this parameter's binding. If this parameter is not
111: * bound, this method returns the parameter. Otherwise, it returns
112: * the bound type.
113: *
114: * @return This parameter's binding.
115: */
116: public Type lookup() {
117: if (null == binding)
118: return this ;
119: if (binding.isParameter())
120: binding = binding.toParameter().lookup();
121: return binding;
122: }
123:
124: public int hashCode() {
125: return name.hashCode();
126: }
127:
128: public boolean equals(Object o) {
129: if (!(o instanceof Type))
130: return false;
131: Type t = resolve(o);
132:
133: if (this == t)
134: return true;
135: if (!t.isParameter())
136: return false;
137: Parameter other = t.toParameter();
138: return name.equals(other.name);
139: }
140:
141: public void write(Appendable out) throws IOException {
142: out.append(name);
143: }
144:
145: public String toString() {
146: return name;
147: }
148:
149: }
|