1 cananian 1.1.2.1 // SWITCH.java, created Wed Aug 26 20:45:24 1998 by cananian
  2 cananian 1.1.2.1 // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu>
  3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 cananian 1.1.2.1 package harpoon.IR.Quads;
  5 cananian 1.1.2.1 
  6 cananian 1.1.2.1 import harpoon.ClassFile.HClass;
  7 cananian 1.1.2.1 import harpoon.ClassFile.HCodeElement;
  8 cananian 1.1.2.1 import harpoon.Temp.Temp;
  9 cananian 1.1.2.1 import harpoon.Temp.TempMap;
 10 cananian 1.1.2.1 import harpoon.Util.Util;
 11 cananian 1.1.2.1 
 12 cananian 1.1.2.1 /**
 13 cananian 1.1.2.3  * <code>TYPESWITCH</code> represents a multiple-way branch dependent on
 14 cananian 1.1.2.5  * the class type of the argument.  It may optionally omit the default
 15 cananian 1.1.2.5  * case, in which case it is read as an assertion on the type of the
 16 cananian 1.1.2.5  * argument, in addition to its usual semantics.
 17 cananian 1.1.2.1  * 
 18 cananian 1.1.2.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 19 cananian 1.5      * @version $Id: TYPESWITCH.java,v 1.5 2002/04/11 04:00:35 cananian Exp $
 20 cananian 1.1.2.1  */
 21 cananian 1.1.2.1 public class TYPESWITCH extends SIGMA {
 22 cananian 1.1.2.3     /** The discriminant, of <code>Object</code> type, whose class is
 23 cananian 1.1.2.3      *  compared against each class type in <code>keys[]</code>.*/
 24 cananian 1.1.2.1     protected Temp index;
 25 cananian 1.1.2.3     /** Class type keys for typeswitch cases. <p>
 26 cananian 1.1.2.1      *  <code>next(n)</code> is the jump target corresponding to
 27 cananian 1.1.2.1      *  <code>keys[n]</code> for <code>0 <= n < keys.length</code>. <p>
 28 cananian 1.1.2.1      *  <code>next(keys.length)</code> is the default target. */
 29 cananian 1.1.2.1     protected HClass keys[];
 30 cananian 1.1.2.5     /** True if this <code>TYPESWITCH</code> has a default case. */
 31 cananian 1.1.2.5     protected boolean hasDefault;
 32 cananian 1.1.2.1 
 33 cananian 1.1.2.1     /** Creates a <code>TYPESWITCH</code> operation. <p>
 34 cananian 1.1.2.1      *  <code>next[n]</code> is the jump target corresponding to
 35 cananian 1.1.2.1      *  <code>keys[n]</code> for <code>0 <= n < keys.length</code>. <p>
 36 cananian 1.1.2.1      *  <code>next[keys.length]</code> is the default target.<p>
 37 cananian 1.1.2.1      *  Order among the keys is important; the destination corresponds
 38 cananian 1.1.2.1      *  to the *first* class type matching the argument.
 39 cananian 1.1.2.1      *  We differ from the modula-3 
 40 cananian 1.1.2.1      * <a href="http://research.compaq.com/SRC/m3defn/html/typecase.html">
 41 cananian 1.1.2.1      * TYPECASE</a> statement by disallowing <code>null</code> as a valid
 42 cananian 1.1.2.2      * key value.  The discriminant is also not permitted to be
 43 cananian 1.1.2.2      * <code>null</code> (except in quad-with-try form, in which case
 44 cananian 1.1.2.2      * a <code>null</code> discriminant causes the default branch to
 45 cananian 1.1.2.5      * be taken).  If <code>withDefault</code> is <code>true</code>,
 46 cananian 1.1.2.5      * a default edge will be taken if none of the keys match the type
 47 cananian 1.1.2.5      * of the argument; otherwise we assert that at least one key will
 48 cananian 1.1.2.5      * always match the argument.
 49 cananian 1.1.2.1      * @param index
 50 cananian 1.1.2.1      *        the discriminant.
 51 cananian 1.1.2.1      * @param keys
 52 cananian 1.1.2.1      *        class type keys for switch cases.
 53 cananian 1.1.2.1      * @param dst
 54 cananian 1.1.2.1      *        sigma function left-hand sides.
 55 cananian 1.1.2.1      * @param src
 56 cananian 1.1.2.1      *        sigma function arguments.
 57 cananian 1.1.2.5      * @param hasDefault
 58 cananian 1.1.2.5      *        <code>true</code> if this <code>TYPESWITCH</code> should
 59 cananian 1.1.2.5      *        have a default case.
 60 cananian 1.1.2.1      */
 61 cananian 1.1.2.1     public TYPESWITCH(QuadFactory qf, HCodeElement source,
 62 cananian 1.1.2.1                       Temp index, HClass keys[],
 63 cananian 1.1.2.5                       Temp dst[][], Temp src[], boolean hasDefault) {
 64 cananian 1.1.2.5         super(qf, source, dst, src, keys.length+(hasDefault?1:0));
 65 cananian 1.1.2.1         this.index = index;
 66 cananian 1.1.2.1         this.keys = keys;
 67 cananian 1.1.2.5         this.hasDefault = hasDefault;
 68 cananian 1.1.2.4         // VERIFY legality of TYPESWITCH.
 69 cananian 1.3.2.1         assert index!=null && keys!=null;
 70 cananian 1.3.2.1         assert keys.length+(hasDefault?1:0)==arity();
 71 cananian 1.1.2.1         for (int i=0; i<keys.length; i++)
 72 cananian 1.3.2.1             assert keys[i]!=null;
 73 cananian 1.1.2.5         // can't have no keys *and* no default.
 74 cananian 1.3.2.1         assert arity()>0;
 75 cananian 1.1.2.1     }
 76 cananian 1.1.2.3     /** Creates a typeswitch with arity defined by the keys array. */
 77 cananian 1.1.2.1     public TYPESWITCH(QuadFactory qf, HCodeElement source,
 78 cananian 1.1.2.5                       Temp index, HClass keys[], Temp src[],
 79 cananian 1.1.2.5                       boolean hasDefault) {
 80 cananian 1.1.2.5         this(qf,source, index, keys,
 81 cananian 1.1.2.5              new Temp[src.length][keys.length+1], src, hasDefault);
 82 cananian 1.1.2.1     }
 83 cananian 1.1.2.1     /** Returns the <code>Temp</code> holding the discriminant. */
 84 cananian 1.1.2.1     public Temp index() { return index; }
 85 cananian 1.1.2.1     /** Returns the array of class type keys for the typeswitch cases. */
 86 cananian 1.1.2.1     public HClass[] keys() { return (HClass[]) keys.clone(); }
 87 cananian 1.1.2.1     /** Returns a given element in the <code>keys</code> array. */
 88 cananian 1.1.2.1     public HClass keys(int i) { return keys[i]; }
 89 cananian 1.1.2.1     /** Returns the length of the <code>keys</code> array. */
 90 cananian 1.1.2.1     public int keysLength() { return keys.length; }
 91 cananian 1.1.2.5     /** Returns <code>true</code> if this <code>TYPESWITCH</code> has a
 92 cananian 1.1.2.5      *  default case. */
 93 cananian 1.1.2.5     public boolean hasDefault() { return hasDefault; }
 94 cananian 1.1.2.1 
 95 cananian 1.1.2.1     /** Returns the <code>Temp</code> used by this quad.
 96 cananian 1.1.2.1      * @return the <code>index</code> field. */
 97 cananian 1.1.2.1     public Temp[] use() { 
 98 cananian 1.1.2.1         Temp[] u = super.use();
 99 cananian 1.1.2.1         Temp[] r = new Temp[u.length+1];
100 cananian 1.1.2.1         System.arraycopy(u, 0, r, 0, u.length);
101 cananian 1.1.2.1         // add 'index' to end of use array.
102 cananian 1.1.2.1         r[u.length] = index;
103 cananian 1.1.2.1         return r;
104 cananian 1.1.2.1     }
105 cananian 1.1.2.1 
106 cananian 1.1.2.1     public int kind() { return QuadKind.TYPESWITCH; }
107 cananian 1.1.2.1 
108 cananian 1.1.2.1     public Quad rename(QuadFactory qqf, TempMap defMap, TempMap useMap) {
109 cananian 1.1.2.1         return new TYPESWITCH(qqf, this, map(useMap,index),
110 cananian 1.1.2.1                               (HClass[])keys.clone(),
111 cananian 1.1.2.5                               map(defMap,dst), map(useMap,src), hasDefault);
112 cananian 1.1.2.1     }
113 cananian 1.1.2.1     /** Rename all used variables in this Quad according to a mapping.
114 cananian 1.1.2.1      * @deprecated does not preserve immutability. */
115 cananian 1.1.2.1     void renameUses(TempMap tm) {
116 cananian 1.1.2.1         super.renameUses(tm);
117 cananian 1.1.2.1         index = tm.tempMap(index);
118 cananian 1.1.2.1     }
119 cananian 1.1.2.1     /** Rename all defined variables in this Quad according to a mapping.
120 cananian 1.1.2.1      * @deprecated does not preserve immutability. */
121 cananian 1.1.2.1     void renameDefs(TempMap tm) {
122 cananian 1.1.2.1         super.renameDefs(tm);
123 cananian 1.1.2.1     }
124 cananian 1.1.2.1 
125 cananian 1.1.2.1     public void accept(QuadVisitor v) { v.visit(this); }
126 cananian 1.5         public <T> T accept(QuadValueVisitor<T> v) { return v.visit(this); }
127 cananian 1.1.2.1 
128 cananian 1.1.2.1     /** Returns human-readable representation of this quad. */
129 cananian 1.1.2.1     public String toString() {
130 cananian 1.1.2.1         StringBuffer sb = new StringBuffer("TYPESWITCH "+index+": ");
131 cananian 1.1.2.1         for (int i=0; i<keys.length; i++)
132 cananian 1.1.2.1             sb.append("case "+keys[i]+"; ");
133 cananian 1.1.2.5         if (!hasDefault) sb.append("no ");
134 cananian 1.1.2.1         sb.append("default");
135 cananian 1.1.2.1         sb.append(" / "); sb.append(super.toString());
136 cananian 1.1.2.1         return sb.toString();
137 cananian 1.1.2.1     }
138 cananian 1.2     }