00001
00005 package edu.mit.csail.sdg.squander.spec;
00006
00007 import java.lang.reflect.Field;
00008 import java.lang.reflect.Modifier;
00009 import java.lang.reflect.ParameterizedType;
00010 import java.lang.reflect.Type;
00011 import java.lang.reflect.TypeVariable;
00012 import java.util.HashMap;
00013 import java.util.Map;
00014
00015 import edu.mit.csail.sdg.squander.spec.ClassSpec.Invariant;
00016 import edu.mit.csail.sdg.squander.spec.JType.Factory;
00017 import edu.mit.csail.sdg.squander.spec.JType.Unary;
00018 import forge.program.ForgeExpression;
00019
00020
00025 public final class JField {
00026
00027 private static final Factory factory = JType.Factory.instance;
00028
00029 private final JType type;
00030 private final JType.Unary owningType;
00031 private final JType.Unary declaringType;
00032 private final String name;
00033 private final Field javaField;
00034
00035
00036
00037 private ForgeExpression domain;
00038 private Invariant absFun;
00039 private Invariant bound;
00040 private Frame frame;
00041 private boolean funcFlag = false;
00042
00043 public static JField newSpecField(String name, Class<?> owner, Class<?> declarer, JType type) {
00044 Unary declaringType = factory.newJType(declarer);
00045 Unary owningType = factory.newJType(owner);
00046 return newSpecField(name, owningType, declaringType, type);
00047 }
00048
00049 public static JField newSpecField(String name, Unary owningType, Unary declaringType, JType type) {
00050 return new JField(name, type, owningType, declaringType, null);
00051 }
00052
00053 public static JField newJavaField(Field f) {
00054 String name = f.getName();
00055 Unary[] typeParams = getTypeParams(f.getGenericType());
00056 Unary type = factory.newJType(f.getType(), typeParams);
00057 Unary declaringType = factory.newJType(f.getDeclaringClass());
00058 return new JField(name, type, declaringType, declaringType, f);
00059 }
00060
00061 JField(String name, JType type, Unary owningType, Unary declaringType, Field javaField) {
00062 this.name = name;
00063 this.type = type;
00064 this.owningType = owningType;
00065 this.declaringType = declaringType;
00066 this.javaField = javaField;
00067 }
00068
00069 public String name() { return name; }
00070 public JType type() { return type; }
00071 public JType.Unary owningType() { return owningType; }
00072 public JType.Unary declaringType() { return declaringType; }
00073 public Field getJavaField() { return javaField; }
00074 public boolean isStatic() { return javaField != null && (javaField.getModifiers() & Modifier.STATIC) != 0; }
00075 public boolean isSpec() { return javaField == null; }
00076 public boolean isFunc() { return isSpec() && funcFlag; }
00077 public boolean isPureAbstract() { return absFun.expr.equals(absFun.expr.program().trueLiteral()); }
00078
00079 public ForgeExpression getDomain() { return domain; }
00080 public Invariant getAbsFun() { return absFun; }
00081 public Invariant getBound() { return bound; }
00082 public Frame getFrame() { return frame; }
00083
00084 public void setDomain(ForgeExpression dom) { this.domain = dom; }
00085 public void setAbsFun(Invariant absFun) { this.absFun = absFun; }
00086 public void setBound(Invariant bound) { this.bound = bound; }
00087 public void setFrame(Frame frame) { this.frame = frame; }
00088 public void setFuncFlag(boolean flag) { this.funcFlag = flag; }
00089
00090 @Override
00091 public boolean equals(Object obj) {
00092 if (obj == null)
00093 return false;
00094 if (!(obj instanceof JField))
00095 return false;
00096 return this.toString().equals(obj.toString());
00097 }
00098
00099 @Override
00100 public int hashCode() {
00101 return toString().hashCode();
00102 }
00103
00104 public String fullName() {
00105 return owningType.simpleName() + "__" + name;
00106 }
00107
00108
00109 public Unary[][] getTypeParams() {
00110 if (javaField != null) {
00111 Unary[] tp = getTypeParams(javaField.getGenericType());
00112 return new Unary[][] { tp };
00113 } else {
00114 Unary[][] tp = new Unary[type.arity()][];
00115 for (int i = 0; i < type.arity(); i++) {
00116 tp[i] = type.projection(i).typeParams();
00117 }
00118 return tp;
00119 }
00120 }
00121
00122 @Override
00123 public String toString() {
00124 StringBuilder sb = new StringBuilder();
00125 if (isSpec()) sb.append("spec ");
00126 if (isStatic()) sb.append("static ");
00127 sb.append(declaringType).append("::");
00128 sb.append(name).append(" ");
00129 sb.append(type);
00130 return sb.toString();
00131 }
00132
00133 private static Map<Type, JType.Unary> cache = new HashMap<Type, Unary>();
00134
00135 public static Unary[] getTypeParams(Type genericType) {
00136 if (genericType instanceof ParameterizedType) {
00137 ParameterizedType pt = (ParameterizedType) genericType;
00138 Type[] actualTypeArgs = pt.getActualTypeArguments();
00139 Unary[] typeParams = new Unary[actualTypeArgs.length];
00140 int idx = 0;
00141 for (Type t : actualTypeArgs) {
00142 typeParams[idx++] = convertToJType(t);
00143 }
00144 return typeParams;
00145 }
00146 return null;
00147 }
00148
00149 public static Unary convertToJType(Type t) {
00150 JType.Unary jtype = cache.get(t);
00151 if (jtype != null)
00152 return jtype;
00153 if (t instanceof Class<?>) {
00154 Class<?> cls = (Class<?>) t;
00155 jtype = JType.Factory.instance.newJType(cls);
00156 cache.put(t, jtype);
00157 return jtype;
00158 } else if (t instanceof ParameterizedType) {
00159 Unary[] typeParams = getTypeParams(t);
00160 Class<?> rawType = (Class<?>) ((ParameterizedType) t).getRawType();
00161 jtype = JType.Factory.instance.newJType(rawType, typeParams);
00162 cache.put(t, jtype);
00163 return jtype;
00164 } else if (t instanceof TypeVariable<?>) {
00165 return JType.Factory.instance.newJType(Object.class);
00166 } else {
00167 throw new RuntimeException("don't know how to convert " + t.getClass().getName() + " to JType");
00168 }
00169 }
00170
00171 }