/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2010.
*/
package x10.types.constraints;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import polyglot.types.SemanticException;
import polyglot.types.Type;
import polyglot.util.Copy;
import polyglot.util.InternalCompilerError;
import x10.constraint.XVar;
import x10.constraint.XTerm;
import x10.types.matcher.Subst;
import x10.types.TypeParamSubst;
/**
* A representation of a subtype constraint, S <: T or S == T.
* TODO: Separate out implementation of haszero T constraint.
*
*/
public class SubtypeConstraint implements Copy, Serializable {
private static final long serialVersionUID = 4026637095619421750L;
public enum Kind {
SUBTYPE, // <:
EQUAL, // ==
HASZERO,
ISREF
}; // haszero
protected Kind KIND;
protected Type subtype;
protected Type supertype;
public SubtypeConstraint(Type subtype, Type supertype, Kind kind) {
this.subtype = subtype;
this.supertype = supertype;
this.KIND = kind;
if (isHaszero() || isIsRef()) assert subtype!=null && supertype==null;
else assert subtype!=null && supertype!=null;
}
public SubtypeConstraint(Type subtype, Type supertype, boolean equals) {
this(subtype, supertype, equals ? Kind.EQUAL : Kind.SUBTYPE);
}
public boolean isEqualityConstraint() { return KIND==Kind.EQUAL; }
public boolean isSubtypeConstraint() { return KIND==Kind.SUBTYPE; }
public boolean isHaszero() { return KIND==Kind.HASZERO; }
public boolean isIsRef() { return KIND==Kind.ISREF; }
public Kind kind() { return KIND;}
/*
* (non-Javadoc)
*
* @see x10.types.SubtypeConstraint#subtype()
*/
public Type subtype() {return subtype;}
/*
* (non-Javadoc)
*
* @see x10.types.SubtypeConstraint#supertype()
*/
public Type supertype() {
// [DC] sometimes you want to create a new SubtypeConstraint based on an old SubtypeConstraint, so null is OK
//assert !isHaszero(); // it returns null if it is haszero constraint, so you don't want to call supertype()
return supertype;
}
public SubtypeConstraint copy() {
try {return (SubtypeConstraint) super.clone();
} catch (CloneNotSupportedException e) {
assert false;
return this;
}
}
public static Type subst(Type t, XTerm y, XVar x) {
try { return Subst.subst(t, y, x);
} catch (SemanticException e) {throw new InternalCompilerError(e);}
}
/*
* (non-Javadoc)
*
* @see x10.types.TypeConstraint#subst(x10.constraint.XTerm,
* x10.constraint.XVar, boolean)
*/
public SubtypeConstraint subst(XTerm y, XVar x) {
Type l = subst(subtype, y, x);
Type r = subst(supertype, y, x);
if (l == subtype && r == supertype) return this;
SubtypeConstraint n = copy();
n.subtype = l;
n.supertype = r;
return n;
}
@Override public String toString() {
if (isHaszero()) {
return subtype() + " haszero";
} else if (isIsRef()) {
return subtype() + " isref";
} else if (isEqualityConstraint()) {
return subtype() + " == " + supertype();
} else if (isSubtypeConstraint()) {
return subtype() + " <: " + supertype();
} else {
throw new RuntimeException("Internal compiler error");
}
}
}