    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