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 }