/**
* Copyright (c) 2009-2011, The HATS Consortium. All rights reserved.
* This file is licensed under the terms of the Modified BSD License.
*/
package abs.frontend.typechecker;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import abs.frontend.ast.Annotation;
import abs.frontend.ast.Decl;
import abs.frontend.ast.FieldDecl;
import abs.frontend.ast.MethodSig;
import abs.frontend.ast.TypeUse;
public abstract class Type {
private static final Object ANNOTATION_KEY = "ANNOTATION_KEY";
protected Map<Object,Object> metaData = new HashMap<Object,Object>();
{
metaData.put(ANNOTATION_KEY, Collections.EMPTY_LIST);
}
public Type withAnnotations(abs.frontend.ast.List<Annotation> anns) {
Type copy = this.fullCopy();
List<TypeAnnotation> newAnnos = new ArrayList<TypeAnnotation>();
@SuppressWarnings("unchecked")
List<TypeAnnotation> annos = (List<TypeAnnotation>) copy.getMetaData(ANNOTATION_KEY);
if (annos != null) {
newAnnos.addAll(annos);
}
newAnnos.addAll(convertToTypeAnnotations(anns));
copy.addMetaData(ANNOTATION_KEY, newAnnos);
return copy;
}
public void addMetaData(Object key, Object value) {
metaData.put(key, value);
}
public Object getMetaData(Object key) {
return metaData.get(key);
}
public Type fullCopy() {
Type copy = copy();
copy.metaData.putAll(metaData);
return copy;
}
protected abstract Type copy();
private List<TypeAnnotation> convertToTypeAnnotations(abs.frontend.ast.List<Annotation> anns) {
ArrayList<TypeAnnotation> res = new ArrayList<TypeAnnotation>();
for (Annotation a : anns) {
Type t = a.getType();
if (t.isAnnotationType()) {
res.add(new TypeAnnotation(a));
}
}
return res;
}
/**
* A string representation of this type
*/
public String toString() {
StringBuilder res = new StringBuilder();
if (!getTypeAnnotations().isEmpty()) {
res.append("[");
boolean first = true;
for (TypeAnnotation a : getTypeAnnotations()) {
if (first) first = false;
else res.append(",");
res.append(a.toString());
}
res.append("] ");
}
res.append(getQualifiedName());
return res.toString();
}
/**
* Returns the full qualified name of this type.
* Returns in general getModuleName()+"."+getSimpleName(),
* if however getModuleName() == null it returns getSimpleName();
* @return the full qualified name of this type
*/
public String getQualifiedName() {
String modulePart = getModuleName();
modulePart = modulePart == null ? "" : modulePart+".";
return modulePart+getSimpleName();
}
/**
* The module name of this type.
* e.g., for type ABS.StdLib.List<Bool> returns ABS.StdLib
* This may return null for special built-in types that
* are not declared in a module
* @return the module name of this type
*/
public String getModuleName() {
return null;
}
/**
* The simple name of this type without the module name.
* Does not include type arguments.
* E.g. for type ABS.StdLib.List<Bool> returns List
* @return the simple name of this type without the module name
*/
public abstract String getSimpleName();
/**
* Whether a type may contain references to objects.
* Reference types are the simplest cases, but
* algebraic types may also contain references.
*/
public boolean hasReferences() {
return isReferenceType();
}
/**
* A type is an annotation type if and only if it is a data type declaration
* and it has an annotation [TypeAnnotation]
* @return
*/
public boolean isAnnotationType() {
return false;
}
public boolean isReferenceType() {
return false;
}
public boolean isInterfaceType() {
return false;
}
public boolean isDataType() {
return false;
}
public boolean isNullType() {
return false;
}
public boolean isTypeParameter() {
return false;
}
public boolean isUnknownType() {
return false;
}
public boolean isFutureType() {
return false;
}
public boolean isBoolType() {
return false;
}
public boolean isUnitType() {
return false;
}
public boolean isStringType() {
return false;
}
public boolean isIntType() {
return false;
}
public boolean isRatType() {
return false;
}
public boolean isNumericType() {
return isIntType() || isRatType();
}
public boolean isExceptionType() {
return false;
}
public boolean isAnyType() {
return false;
}
public boolean isDeploymentComponentType() {
return false;
}
public MethodSig lookupMethod(String name) {
return null;
}
public boolean equals(Object o) {
if (o == null)
return false;
if (!(o instanceof Type))
return false;
System.err.println(this+":"+o);
return true;
}
public int hashCode() {
assert false : "hashCode not designed:"+this;
return 42; // any arbitrary constant will do
}
public boolean isBoundedType() {
return false;
}
public boolean isAssignableTo(Type t, boolean considerSubtyping) {
return isAssignableTo(t);
}
public boolean isAssignableTo(Type t) {
if (t == null)
throw new IllegalArgumentException("t is null");
if (t.isAnyType())
return true;
if (this.equals(t))
return true;
if (t.isBoundedType()) {
BoundedType bt = (BoundedType) t;
if (bt.hasBoundType())
return this.isAssignableTo(bt.getBoundType());
bt.bindTo(this);
return true;
}
return false;
}
public boolean isUnionType() {
return false;
}
public boolean canBeBoundTo(Type t) {
return false;
}
@SuppressWarnings("unchecked")
public List<TypeAnnotation> getTypeAnnotations() {
return Collections.unmodifiableList((List<TypeAnnotation>) getMetaData(ANNOTATION_KEY));
}
public Collection<MethodSig> getAllMethodSigs() {
return Collections.emptyList();
}
public Collection<FieldDecl> getAllFieldDecls() {
return Collections.emptyList();
}
/**
* returns the declaration of this type or null if there is no
* declaration for this type
*/
public Decl getDecl() {
return null;
}
public Type applyBinding(Map<TypeParameter, Type> binding) { return this; }
/**
* Use by the rewriting logic for AwaitAsyncCalls in GenerateCoreAbs.
*/
public TypeUse toUse() {
assert false : "Should never happen for a well-typed model:" + getClass().getSimpleName()+"/"+getSimpleName();
return null;
}
}