Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

Ref.java

00001 package edu.ksu.cis.bandera.bir;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Bandera, a Java(TM) analysis and transformation toolkit           *
00005  * Copyright (C) 1998, 1999   James Corbett (corbett@hawaii.edu)     *
00006  * All rights reserved.                                              *
00007  *                                                                   *
00008  * This work was done as a project in the SAnToS Laboratory,         *
00009  * Department of Computing and Information Sciences, Kansas State    *
00010  * University, USA (http://www.cis.ksu.edu/santos).                  *
00011  * It is understood that any modification not identified as such is  *
00012  * not covered by the preceding statement.                           *
00013  *                                                                   *
00014  * This work is free software; you can redistribute it and/or        *
00015  * modify it under the terms of the GNU Library General Public       *
00016  * License as published by the Free Software Foundation; either      *
00017  * version 2 of the License, or (at your option) any later version.  *
00018  *                                                                   *
00019  * This work is distributed in the hope that it will be useful,      *
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00022  * Library General Public License for more details.                  *
00023  *                                                                   *
00024  * You should have received a copy of the GNU Library General Public *
00025  * License along with this toolkit; if not, write to the             *
00026  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00027  * Boston, MA  02111-1307, USA.                                      *
00028  *                                                                   *
00029  * Java is a trademark of Sun Microsystems, Inc.                     *
00030  *                                                                   *
00031  * To submit a bug report, send a comment, or get the latest news on *
00032  * this project and other SAnToS projects, please visit the web-site *
00033  *                http://www.cis.ksu.edu/santos                      *
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  * A reference type.
00046  * <p>
00047  * A reference in BIR is defined with a set of state variables (which
00048  * must be records or arrays) to which it can refer.  A reference
00049  * can also refer to a collection, in which case the reference points
00050  * to an element of the collection.
00051  * <p>
00052  * Since reference types can be declared before the state variables
00053  * to which they refer, reference types must be resolved by finding
00054  * the variables named in the type and connecting them to the reference
00055  * type.
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      * Create a resolved reference type that can refer to 
00067      * a specific state variable.
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      * Create a resolved reference type that can refer to 
00079      * a specific set of state variables.
00080      */
00081     public Ref(StateVarVector targets, TransSystem system) {
00082     this.targets = targets;
00083     this.targetType = new Record();
00084     this.system = system;
00085     }
00086     /**
00087      * Create an empty, unresolved reference type
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         // targetType = superType(targetType,
00112         //                   liftCollectionType(var.getType()));
00113         //
00114         // This is a massive hack. It couples BIR to Soot and BIRC!
00115         // We really want a cleaner way of doing this. Perhaps an
00116         // explicit representation of the BIR type hierarchy is in order.
00117         //
00118         // Right now, inheritence is detected by field name/type/ordering
00119         // (i.e., if type a is a prefix of type b then its a parent). Fortunately,
00120         // the BIRC Builder only forces this "paternity test" on BIR types
00121         // that are known to be derived from related Soot types.
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      * The target type of a reference type is the least common supertype
00136      * of all the types of its targets.  The empty record is a supertype
00137      * of all types since no operations can be performed to it.
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) { // Robbyjo's patch
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      * Test if type is a subtype of another (i.e., contains a subset of
00164      * its targets).
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      * Return the base type of a collection.
00178      */
00179 
00180     Type liftCollectionType(Type type) {
00181     return type.isKind(COLLECTION) ? 
00182         ((Collection)type).getBaseType() : type;
00183     }
00184     /**
00185      * Resolve a reference type by finding the state variables
00186      * named in the type and computing the target type.
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      * Compute the least common supertype of two types.
00205      */
00206      
00207     Type superType(Type type1, Type type2) {
00208     if (type1 == type2)
00209         return type1;
00210     // If both arrays of same type, return the one with smaller size
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     // If both records, one must have a subset of the other's fields
00219     // Return the smaller type
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     // Else ref is to any object, return empty record
00233 
00234 // Here's where we need to query the type hierarchy
00235 //   to find the least ancestor type and return it
00236 //
00237 // In fact, type hierarchy information can be used to replace this entire
00238 // method.
00239     return new Record();
00240     }
00241     // Printing
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 }

Generated at Thu Feb 7 06:53:45 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001