/*
* xtc - The eXTensible Compiler
* Copyright (C) 2007-2008 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;
/**
* The superclass of all type parameters. When a type is
* parameterized, all occurrences of the same parameter should also be
* the same instance of a subclass. Furthermore, the type should be
* wrapped in a {@link ParameterizedT} listing all parameters.
* Instantiation of a parameterized type does not require replacing
* all parameters, but rather should be implemented by wrapping the
* paramterized type in an {@link InstantiatedT} listing all
* arguments. To support efficient unification, this class implements
* union/find operations with path compression through the {@link
* #bind(Type)} and {@link #lookup()} operations.
*
* @author Robert Grimm
* @version $Revision: 1.4 $
*/
public abstract class Parameter extends Type {
/** The binding. */
private Type binding;
/** Create a new parameter. */
public Parameter() {
// Nothing to do.
}
/**
* Create a new parameter.
*
* @param template The type whose annotations to copy.
*/
public Parameter(Type template) {
super(template);
}
public boolean isParameter() {
return true;
}
public Parameter toParameter() {
return this;
}
/**
* Bind this parameter to the specified type.
*
* @param type The type.
* @throws IllegalStateException Signals that this parameter is
* sealed or already bound.
*/
public void bind(Type type) {
checkNotSealed();
if (null != binding) {
throw new IllegalStateException("Parameter already bound");
}
binding = type;
if (binding.isParameter()) binding = binding.toParameter().lookup();
}
/**
* Look up this parameter's binding. If this parameter is not
* bound, this method returns the parameter. Otherwise, it returns
* the bound type.
*
* @return This parameter's binding.
*/
public Type lookup() {
if (null == binding) return this;
if (binding.isParameter()) binding = binding.toParameter().lookup();
return binding;
}
}