00001 package edu.ksu.cis.bandera.bir;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 import ca.mcgill.sable.util.*;
00036 import ca.mcgill.sable.soot.SootClass;
00037
00038 import java.io.*;
00039 import java.util.*;
00040
00041 import edu.ksu.cis.bandera.birc.TypeExtractor;
00042 import edu.ksu.cis.bandera.prog.HierarchyQuery;
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 public class Ref extends Type implements BirConstants {
00059
00060 TransSystem system;
00061 StateVarVector targets;
00062 Vector targetNames;
00063 Type targetType;
00064 SootClass sootType;
00065
00066
00067
00068
00069 public Ref(StateVar target) {
00070 this.targetNames = new Vector(10);
00071 this.targetNames.addElement(target.getName());
00072 this.targets = new StateVarVector(1);
00073 this.targets.addElement(target);
00074 this.targetType = liftCollectionType(target.getType());
00075 this.system = target.getSystem();
00076 }
00077
00078
00079
00080
00081 public Ref(StateVarVector targets, TransSystem system) {
00082 this.targets = targets;
00083 this.targetType = new Record();
00084 this.system = system;
00085 }
00086
00087
00088
00089 public Ref(TransSystem system) {
00090 this.targetNames = new Vector(10);
00091 this.system = system;
00092 }
00093 public void addTarget(StateVar var) {
00094 if (targets == null)
00095 targets = new StateVarVector(10);
00096 targets.addElement(var);
00097 if (targets.size() == 1)
00098 targetType = liftCollectionType(var.getType());
00099 else
00100 targetType = superType(targetType,
00101 liftCollectionType(var.getType()));
00102 }
00103 public void addTarget(StateVar var, SootClass sootClass, TypeExtractor extractor) {
00104 if (targets == null)
00105 targets = new StateVarVector(10);
00106 targets.addElement(var);
00107 if (targets.size() == 1) {
00108 targetType = liftCollectionType(var.getType());
00109 sootType = sootClass;
00110 } else {
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 sootType = HierarchyQuery.leastAncestor(sootType, sootClass);
00124 targetType = extractor.getRecordType(sootType);
00125 }
00126 }
00127 public void addTarget(String name) {
00128 targetNames.addElement(name);
00129 }
00130 public void apply(TypeSwitch sw, Object o)
00131 {
00132 sw.caseRef(this, o);
00133 }
00134
00135
00136
00137
00138
00139
00140 Type computeTargetType() {
00141 Type result = liftCollectionType(targets.elementAt(0).getType());
00142 for (int i = 1; i < targets.size(); i++) {
00143 Type targetType = targets.elementAt(i).getType();
00144 result = superType(result, liftCollectionType(targetType));
00145 }
00146 return result;
00147 }
00148 public boolean containsValue(Object value) {
00149 return (value instanceof NullExpr) || (value instanceof RefLit);
00150 }
00151 public Expr defaultVal() {
00152 return new NullExpr(system);
00153 }
00154 public boolean equals(Object o) {
00155 return this == o;
00156 }
00157 public StateVarVector getTargets() { return targets; }
00158 public Type getTargetType() { return targetType; }
00159 public boolean isKind(int kind) {
00160 return (kind & REF) != 0;
00161 }
00162
00163
00164
00165
00166
00167 public boolean isSubtypeOf(Type type) {
00168 if (! type.isKind(REF))
00169 return false;
00170 Ref other = (Ref) type;
00171 for (int i = 0; i < this.targets.size(); i++)
00172 if (! other.targets.contains(this.targets.elementAt(i)))
00173 return false;
00174 return true;
00175 }
00176
00177
00178
00179
00180 Type liftCollectionType(Type type) {
00181 return type.isKind(COLLECTION) ?
00182 ((Collection)type).getBaseType() : type;
00183 }
00184
00185
00186
00187
00188 public void resolveTargets() {
00189 targets = new StateVarVector(targetNames.size());
00190 for (int i = 0; i < targetNames.size(); i++) {
00191 String name = (String) targetNames.elementAt(i);
00192 Object key = system.getKeyOf(name);
00193 if (key == null)
00194 throw new RuntimeException("Unknown object in Ref type: "
00195 + name);
00196 StateVar var = system.getVarOfKey(key);
00197 if (! var.getType().isKind(RECORD | ARRAY | COLLECTION))
00198 throw new RuntimeException("Ref type must refer to record, array or collection: " + name + " is a " + var.getType());
00199 targets.addElement(var);
00200 }
00201 targetType = computeTargetType();
00202 }
00203
00204
00205
00206
00207 Type superType(Type type1, Type type2) {
00208 if (type1 == type2)
00209 return type1;
00210
00211 if (type1.isKind(ARRAY) && type2.isKind(ARRAY)
00212 && (((Array)type1).getBaseType() == ((Array)type2).getBaseType()))
00213 if (((Array)type1).getSize().getValue() >
00214 ((Array)type2).getSize().getValue())
00215 return type2;
00216 else
00217 return type1;
00218
00219
00220 if (type1.isKind(RECORD) && type2.isKind(RECORD)) {
00221 int i;
00222 Vector fields1 = ((Record)type1).getFields();
00223 Vector fields2 = ((Record)type2).getFields();
00224 for (i = 0; i < fields1.size() && i < fields2.size(); i++)
00225 if (! fields2.elementAt(i).equals(fields1.elementAt(i)))
00226 break;
00227 if (i == fields1.size())
00228 return type1;
00229 if (i == fields2.size())
00230 return type2;
00231 }
00232
00233
00234
00235
00236
00237
00238
00239 return new Record();
00240 }
00241
00242 public String toString() {
00243 if (this == system.refAnyType())
00244 return "ref { * }";
00245 String result = targets.elementAt(0).getName();
00246 for (int i = 1; i < targets.size(); i++)
00247 result += ", " + targets.elementAt(i).getName();
00248 return "ref { " + result + " }";
00249 }
00250 }