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

TransSystem.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 
00037 import java.io.*;
00038 import java.util.*;
00039 
00040 /**
00041  * A BIR transition system.
00042  * <p>
00043  * This is the top-level object encapsulating a transition system. 
00044  * It contains:
00045  * <ul>
00046  * <li> A name for the system (this is used for filename generation).
00047  * <li> A set of threads.
00048  * <li> A set of state variables.
00049  * <li> A set of definitions.
00050  * <li> Tables associating BIR entities with external keys
00051  * (useful when constructing the transition system from
00052  * another representation).
00053  * <li> A naming service (for assigning globally unique names).
00054  * </ul>
00055  */
00056 
00057 public class TransSystem implements BirConstants {
00058 
00059     String name;                // Name of system (for filename generation)
00060     int threadCount = 0;        // Number of threads
00061     int locCount = 0;           // Number of locations in all threads
00062     int stateSize = 0;          // Size of state vector needed
00063 
00064     ThreadVector threadVector = new ThreadVector();        // threads
00065     StateVarVector stateVarVector = new StateVarVector();  // state vars
00066     TransVector transVector = new TransVector();           // transformations
00067     Vector definitionVector = new Vector();                // definitions
00068     Vector typeVector = new Vector();                      // types
00069 
00070     Hashtable definitionTable = new Hashtable();  // map String --> Definition
00071     Hashtable locationOfKey = // map Key --> Location
00072     new Hashtable();
00073     Hashtable stateVarOfKey = // map Key --> StateVar
00074     new Hashtable();
00075     Hashtable sourceMap =  // map BIR object --> Source Object 
00076     new Hashtable();
00077 
00078     Location [] locationTable;  // map loc number --> Location
00079     int numberedLocs;           // Numbered locations
00080 
00081     Hashtable nameTable = new Hashtable();   // set of (global) names 
00082     Hashtable namedKeyTable = new Hashtable();  // map Object --> String (name)
00083     Hashtable threadTable = new Hashtable();  // map Object --> BirThread
00084 
00085     Hashtable predTable = new Hashtable();    // assoc Predicate <-> Name
00086     Vector predVector = new Vector();        // list of predicates
00087 
00088     // The set of all collections (used to build the universal ref type).
00089     StateVarVector refTargets = new StateVarVector();
00090     Ref refAnyType = new Ref(refTargets,this);
00091 
00092     /**
00093      * This is the set of names that cannot be used for declared entities
00094      * in a BIR transition system (because they are used by BIR or one
00095      * of the translator input languages).
00096      */
00097 
00098     static String [] reservedNames = { 
00099     // Rerserved by BIR
00100     "array",
00101     "boolean",
00102     "choose",
00103     "collection",
00104     "do",
00105     "end",
00106     "enum",
00107     "exit",
00108     "false",
00109     "goto",
00110     "hasLock",
00111     "instanceof",
00112     "invisible",
00113     "join",
00114     "live",
00115     "loc",
00116     "lock",
00117     "lockAvailable",
00118     "main",
00119     "new",
00120     "notify",
00121     "notifyAll",
00122     "null",
00123     "of",
00124     "predicates",
00125     "println",
00126     "process",
00127     "reentrant",
00128     "range",
00129     "record",
00130     "ref",
00131     "start",
00132     "thread",
00133     "threadTerminated",
00134     "true",
00135     "unlock",
00136     "unwait",
00137     "wait",
00138     "wasNotified",
00139     "when",
00140     // Rerserved by SPIN
00141     "active",
00142     "assert",
00143     "atomic",
00144     "bit",
00145     "bool",
00146     "break",
00147     "byte",
00148     "chan",
00149         "d_step",
00150     "Dproctype",
00151     "do",
00152     "else",
00153         "empty",
00154     "enabled",
00155     "fi",
00156     "full",
00157         "goto",
00158     "hidden",
00159     "if",
00160     "init",
00161         "int",
00162     "len",
00163     "mtype",
00164     "nempty",
00165         "never",
00166     "nfull",
00167     "od",
00168     "of",
00169         "pcvalue",
00170     "printf",
00171     "priority",
00172         "proctype",
00173         "provided",
00174         "run",
00175     "short",
00176     "skip",
00177         "timeout",
00178     "typedef",
00179     "unless",
00180     "unsigned",
00181         "xr",
00182     "xs",
00183     "type",
00184     // Reserved by SMV
00185     "DEFINE",
00186     "FAIRNESS",
00187     "MODULE",
00188     "SPEC",
00189     "TRANS",
00190     "VAR",
00191         "INIT",
00192         "next"
00193     };
00194     /**
00195      * Create a transition system with the given name.
00196      */
00197 
00198     public TransSystem(String name) {
00199     reserveNames();
00200     this.name = createName(null, name);
00201     }
00202     /**
00203      * Add transformation.
00204      */
00205     public void addTrans(Transformation trans) {
00206     transVector.addElement(trans);
00207     }
00208 public void addType(Type t) // Robbyjo's patch
00209 {
00210     typeVector.addElement(t);
00211 }
00212     /**
00213      * Create array type
00214      */
00215     public Array arrayType(Type baseType, ConstExpr size) { 
00216     Array type = new Array(baseType,size);
00217     type.setTypeId(createName(null,"type"));
00218     typeVector.addElement(type);
00219     return type;
00220     }
00221     /**
00222      * Create boolean type
00223      */
00224     public Bool booleanType() { 
00225     Bool type = (Bool) Type.booleanType; 
00226     if (type.getTypeId() == null) {
00227         type.setTypeId(createName(null,"type"));
00228         typeVector.addElement(type);
00229     }
00230     return type;
00231     }
00232     /**
00233      * Create collection type
00234      */
00235     public Collection collectionType(Type baseType, ConstExpr size) { 
00236     Collection type = new Collection(baseType,size);
00237     type.setTypeId(createName(null,"type"));
00238     typeVector.addElement(type);
00239     return type;
00240     }
00241     /**
00242      * Create a unqiue name for an external key, given a proposed name
00243      * @param key key of entity (may be null)
00244      * @param proposedName proposed name
00245      * @return unique name close to proposed name
00246      * <p>
00247      * To facilitate translation, we make the names of all declared
00248      * entities (variables, threads, definitions) unique using this
00249      * service.
00250      * <p>
00251      * The actual name is constructed from the proposed name by
00252      * replacing '$' and '.' (which appear in nested class/package names)
00253      * with '_' (yielding a string we call the 'prefix')
00254      * and proceding as follows:
00255      * <ul>
00256      * <li> If the prefix is not yet taken, use it.
00257      * <li> Otherwise, if the prefix concatenated to "_0" is
00258      * not yet taken, use it.
00259      * <li> Continue trying names formed by appending "_1", "_2", etc.
00260      * to the prefix until we find a name that is not yet in use.
00261      * </ul>
00262      */
00263     public String createName(Object key, String proposedName) {
00264     String prefix = proposedName.replace('$','_').replace('.','_');
00265     String name = prefix;
00266     int count = 0;
00267     while (nameTable.get(name) != null) 
00268         name = prefix + "_" + (count++);
00269     nameTable.put(name,(key != null) ? key : name);
00270     if (key != null) {
00271         Object nameOfKey = namedKeyTable.get(key);
00272         if (nameOfKey != null)
00273         throw new RuntimeException("Redefinition of name for: " + key);
00274         namedKeyTable.put(key,name);
00275     }
00276     return name;
00277     }
00278     /**
00279      * Create a thread.
00280      * @param proposedName the proposed name of the thread
00281      * @param key external key to associate with thread
00282      * @return new thread
00283      */
00284     public BirThread createThread(String proposedName, Object key) {
00285     String name = createName(key, proposedName);
00286     BirThread thread = new BirThread(this, name, threadVector.size());
00287     threadVector.addElement(thread);
00288     threadTable.put(key, thread);
00289     setSource(thread,key);
00290     return thread;
00291     }
00292     /**
00293      * Declare a predicate
00294      * @param proposedName the proposed name
00295      * @param expr the value of the predicate (and expression on the state)
00296      * <p>
00297      * Note: if the proposed name is not legal (e.g., is reserved or
00298      * already taken), then the name is changed, but the front end
00299      * is not informed---this should be fixed at some point.
00300      */
00301 
00302     public void declarePredicate(String proposedName, Expr expr) {
00303     if (getKeyOf(proposedName) != null)
00304         throw new RuntimeException("Redefinition of " + proposedName);
00305     String name = createName(proposedName,proposedName);
00306     predTable.put(name,expr);
00307     predTable.put(expr,name);
00308     predVector.addElement(expr);
00309     }
00310     /**
00311      * Declare a new state variable.
00312      * @param key external key associated with state variable
00313      * @param proposedName proposed name of variable
00314      * @param thread thread containing variable (null if global)
00315      * @param type type of variable
00316      * @param initVal initial value (if null, uses default for type)
00317      * @return new state variable
00318      */
00319     public StateVar declareVar(Object key, String proposedName, 
00320                    BirThread thread, Type type, Expr initVal) {
00321     Object value = stateVarOfKey.get(key);
00322     if (value != null)
00323         throw new RuntimeException("Variable already declared: " + name);
00324     String name = createName(key,proposedName);
00325     StateVar var = new StateVar(name, thread, type, initVal, this);
00326     if (type.isKind(COLLECTION | RECORD | ARRAY))
00327         refTargets.addElement(var);
00328     stateVarVector.addElement(var);
00329     stateVarOfKey.put(key, var);
00330     setSource(var,key);
00331     return var;
00332     }
00333     /**
00334      * Add definition, associate it with a key.
00335      */
00336     public void define(Object key, Definition definition) {
00337     definitionTable.put(key, definition);
00338     definitionVector.addElement(definition);
00339     }
00340     /**
00341      * Create enumerated type
00342      */
00343     public Enumerated enumeratedType() { 
00344     Enumerated type = new Enumerated();
00345     type.setTypeId(createName(null,"type"));
00346     typeVector.addElement(type);
00347     return type;
00348     }
00349     /**
00350      * Get definition associated with key.
00351      */
00352     public Definition getDefinition(Object key) { 
00353     return (Definition) definitionTable.get(key);
00354     }
00355     public Vector getDefinitions() { return definitionVector; }
00356     /**
00357      * Get the key associated with a name.
00358      */
00359     public Object getKeyOf(String name) {
00360     return nameTable.get(name);
00361     }
00362     /**
00363      * Get the local variables of a thread.
00364      */
00365     
00366     public StateVarVector getLocalStateVars(BirThread thread) {
00367     StateVarVector vars = new StateVarVector();
00368     for (int i = 0; i < stateVarVector.size(); i++) 
00369         if (stateVarVector.elementAt(i).getThread() == thread)
00370         vars.addElement(stateVarVector.elementAt(i));
00371     return vars;
00372     }
00373     public Location getLocation(int id) { 
00374     if (locationTable == null)
00375         throw new RuntimeException("Must invoke numberLocations() before getLocation()");
00376     return locationTable[id];
00377     }
00378     // Accessors
00379 
00380     public String getName() { return name; }
00381     /**
00382      * Get the name associated with a key.
00383      */
00384     public String getNameOf(Object key) {
00385     return (String) namedKeyTable.get(key);
00386     }
00387     public Vector getPredicates() { return predVector; }
00388     /**
00389      * Get the source of a BIR object.
00390      */
00391     public Object getSource(Object birObject) {
00392     return sourceMap.get(birObject);
00393     }
00394     public StateVarVector getStateVars() { return stateVarVector; }
00395     public ThreadVector getThreads() { return threadVector; }
00396     /**
00397      * Get the set of transformations (all threads).
00398      */
00399     public TransVector getTransformations() { return transVector; }
00400     public Vector getTypes() { return typeVector; }
00401     /**
00402      * Retrieve state variable associated with key.
00403      */
00404     public StateVar getVarOfKey(Object key) {
00405     return (StateVar) stateVarOfKey.get(key);
00406     }
00407     /**
00408      * Retrieve location associated with key, or create a new
00409      * location (if none is found).
00410      * @param key external key associated with location
00411      * @param thread thread containing location
00412      * @return new location or old location associated with key
00413      */
00414     public Location locationOfKey(Object key, BirThread thread) {
00415     if (key == null) {
00416         locCount++;
00417         return new Location(thread);
00418     }
00419     Object value = locationOfKey.get(key);
00420     if (value != null)
00421         return (Location) value;
00422     Location loc = new Location(thread);
00423     locCount++;
00424     locationOfKey.put(key, loc);
00425     return loc;
00426     }
00427     /**
00428      * Create lock type
00429      */
00430     public Lock lockType(boolean waiting, boolean reentrant) { 
00431     Lock type = new Lock(waiting,reentrant);
00432     type.setTypeId(createName(null,"type"));
00433     typeVector.addElement(type);
00434     return type;
00435     }
00436     void numberLoc(Location loc, LocVector threadLocVector) {
00437     if (loc.getId() < 0) {
00438         threadLocVector.addElement(loc);
00439         loc.setId(++numberedLocs);
00440         locationTable[numberedLocs] = loc;
00441         for (int i = 0; i < loc.getOutTrans().size(); i++) {
00442         Transformation trans = (Transformation)
00443             loc.getOutTrans().elementAt(i);
00444         numberLoc(trans.getToLoc(), threadLocVector);
00445         }
00446     }
00447     }
00448     /**
00449      * Number the (reachable) locations depth first (chiefly so they'll
00450      * print out in a nice order).
00451      */
00452     public void numberLocations() {
00453     numberedLocs = 0;
00454     locationTable = new Location[locCount + 1];
00455     for (int i = 0; i < threadVector.size(); i++) {
00456         BirThread thread = threadVector.elementAt(i);
00457         LocVector threadLocVector = new LocVector();
00458         numberLoc(thread.startLoc, threadLocVector);
00459         thread.setLocations(threadLocVector);
00460     }
00461     }
00462     /**
00463      * Retrieve the name of a predicate given its expression
00464      */
00465 
00466     public String predicateName(Object predicate) {
00467     return (String) predTable.get(predicate);
00468     }
00469     /**
00470      * Create default range type
00471      */
00472     public Range rangeType() { 
00473     Range type = (Range) Type.defaultRangeType; 
00474     type = new Range(type.getFromVal(), type.getToVal());
00475     int index = typeVector.indexOf(type);
00476     if (index >= 0)
00477         return (Range) typeVector.elementAt(index);
00478     else
00479         return rangeType(type.getFromVal(), type.getToVal());
00480     }
00481     /**
00482      * Create specific range type
00483      */
00484     public Range rangeType(ConstExpr lo, ConstExpr hi) { 
00485     Range type = new Range(lo,hi);
00486     type.setTypeId(createName(null,"type"));
00487     typeVector.addElement(type);
00488     return type;
00489     }
00490     /**
00491      * Create record type
00492      */
00493     public Record recordType() { 
00494     Record type = new Record();
00495     type.setTypeId(createName(null,"type"));
00496     // Robbyjo's patch
00497     //typeVector.addElement(type);
00498     return type;
00499     }
00500     /**
00501      * Return ref any type
00502      */
00503     public Ref refAnyType() { 
00504     return refAnyType;
00505     }
00506     /**
00507      * Create ref type
00508      */
00509     public Ref refType() { 
00510     Ref type = new Ref(this);
00511     type.setTypeId(createName(null,"type"));
00512     typeVector.addElement(type);
00513     return type;
00514     }
00515     void reserveNames() {
00516     for (int i = 0; i < reservedNames.length; i++) 
00517         nameTable.put(reservedNames[i], reservedNames[i]);
00518     }
00519     /**
00520      * Set the source (an arbitrary object) of a BIR object
00521      * <p>
00522      * This is used to map a BIR action back to the entity
00523      * (e.g., a Jimple statement) from which it was generated.
00524      */
00525     public void setSource(Object birObject, Object source) {
00526     sourceMap.put(birObject, source);
00527     }
00528     /**
00529      * Retrieve thread associated with key.
00530      */
00531     public BirThread threadOfKey(Object key) {
00532     return (BirThread) threadTable.get(key);
00533     }
00534 }

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