001    /* Copyright 2000, 2001, Compaq Computer Corporation */
002    
003    package escjava.translate;
004    
005    
006    import java.util.Hashtable;
007    import java.util.Enumeration;
008    
009    import javafe.ast.*;
010    import javafe.util.Set;
011    import javafe.util.Assert;
012    
013    import escjava.ast.*;
014    import escjava.ast.TagConstants;
015    
016    
017    /**
018     ** Provides methods for computing various kinds of syntactic targets
019     **/
020    
021    public final class Targets {
022      
023      /** Returns the set of normal targets of <code>gc</code>.
024        * In ESCJ 16 speak, this method returns <code>NTargets[[ gc, {} ]]</code>.
025        **/
026    
027      //@ ensures \result != null;
028      public static Set normal(/*@ non_null */ GuardedCmd gc) {
029        // use the SimpleTargets option (see ESCJ 16)
030        Set answer = new Set();
031        simpleTargets(gc, answer, true);
032        return answer;
033      }
034    
035      /** Returns the set of variables that are direct normal targets in
036        * <code>gc</code>, that is, that are modified in some assignment
037        * statement, not call statement, in <code>gc</code>.
038        **/
039    
040      //@ ensures \result != null;
041      public static Set direct(/*@ non_null */ GuardedCmd gc) {
042        // use the SimpleTargets option (see ESCJ 16)
043        Set answer = new Set();
044        simpleTargets(gc, answer, false);
045        return answer;
046      }
047    
048      /** Adds <code>SimpleTargets[[ gc ]]</code> (as defined in ESCJ 16)
049        * to <code>set</code>.  Assumes that no local variable declared in
050        * <code>gc</code> is in <code>set</code>.  If
051        * <code>includeCallTargets</code> is <code>true</code>, the targets of
052        * calls are included; otherwise, they are not.
053        **/
054    
055      private static void simpleTargets(/*@ non_null */ GuardedCmd gc, Set set,
056                                        boolean includeCallTargets) {
057        int tag = gc.getTag();
058        switch (tag) {
059        case TagConstants.SKIPCMD:
060        case TagConstants.RAISECMD:
061        case TagConstants.ASSERTCMD:
062        case TagConstants.ASSUMECMD:
063          return;
064    
065        case TagConstants.GETSCMD: {
066          GenericVarDecl vd = ((GetsCmd)gc).v.decl;
067          set.add(vd);
068          return;
069        }
070    
071        case TagConstants.SUBGETSCMD: {
072          GenericVarDecl vd = ((SubGetsCmd)gc).v.decl;
073          set.add(vd);
074          return;
075        }
076    
077        case TagConstants.SUBSUBGETSCMD: {
078          GenericVarDecl vd = ((SubSubGetsCmd)gc).v.decl;
079          set.add(vd);
080          return;
081        }
082    
083        case TagConstants.RESTOREFROMCMD: {
084          // no targets
085          return;
086        }
087    
088        case TagConstants.VARINCMD: {
089          VarInCmd vc = (VarInCmd)gc;
090          simpleTargets(vc.g, set, includeCallTargets);
091          for (int i = 0; i < vc.v.size(); i++) {
092            GenericVarDecl vd = vc.v.elementAt(i);
093            set.remove(vd);
094          }
095          return;
096        }
097    
098        case TagConstants.DYNINSTCMD: {
099          DynInstCmd dc = (DynInstCmd)gc;
100          simpleTargets(dc.g, set, includeCallTargets);
101          return;
102        }
103    
104        case TagConstants.SEQCMD: {
105          SeqCmd sc = (SeqCmd)gc;
106          int len = sc.cmds.size();
107          for (int i = 0; i < len; i++) {
108            simpleTargets(sc.cmds.elementAt(i), set, includeCallTargets);
109          }
110          return;
111        }
112    
113        case TagConstants.CALL: {
114            Call call = (Call)gc;
115            if (call.inlined) {
116                simpleTargets(call.desugared, set, includeCallTargets);
117            } else if (includeCallTargets) {
118                Enumeration e = call.spec.preVarMap.keys();
119                while (e.hasMoreElements()) {
120                    set.add(((GenericVarDecl)e.nextElement()));
121                }
122            }
123            return;
124        }
125    
126        case TagConstants.TRYCMD: {
127          CmdCmdCmd tc = (CmdCmdCmd)gc;
128          simpleTargets(tc.g1, set, includeCallTargets);
129          simpleTargets(tc.g2, set, includeCallTargets);
130          return;
131        }
132    
133        case TagConstants.LOOPCMD: {
134          LoopCmd lp = (LoopCmd)gc;
135          simpleTargets(lp.guard, set, includeCallTargets);
136          simpleTargets(lp.body, set, includeCallTargets);
137          for (int i = 0; i < lp.tempVars.size(); i++) {
138            GenericVarDecl vd = lp.tempVars.elementAt(i);
139            set.remove(vd);
140          }
141          return;
142        }
143    
144        case TagConstants.CHOOSECMD: {
145          CmdCmdCmd cc = (CmdCmdCmd)gc;
146          simpleTargets(cc.g1, set, includeCallTargets);
147          simpleTargets(cc.g2, set, includeCallTargets);
148          return;
149        }
150    
151        default:
152          //@ unreachable;
153          Assert.fail("UnknownTag<" + tag + ":" +
154                      TagConstants.toString(tag) + ">");
155          return;
156        }
157      }
158      
159    }
160