1 pnkfelix 1.1.2.1 // MaximalMunchCGG.java, created Thu Jun 24 18:07:16 1999 by pnkfelix 2 pnkfelix 1.1.2.1 // Copyright (C) 1999 Felix S. Klock II <pnkfelix@mit.edu> 3 pnkfelix 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 pnkfelix 1.1.2.1 package harpoon.Tools.PatMat; 5 pnkfelix 1.1.2.1 6 pnkfelix 1.1.2.4 import harpoon.Util.Util; 7 pnkfelix 1.1.2.4 import harpoon.IR.Tree.Type; 8 cananian 1.1.2.35 import harpoon.IR.Tree.PreciselyTyped; 9 pnkfelix 1.1.2.30 import harpoon.IR.Tree.SEGMENT; 10 cananian 1.1.2.34 import harpoon.IR.Tree.Bop; 11 cananian 1.1.2.34 import harpoon.IR.Tree.Uop; 12 pnkfelix 1.1.2.4 13 pnkfelix 1.1.2.2 import java.io.PrintWriter; 14 pnkfelix 1.1.2.4 import java.util.Comparator; 15 pnkfelix 1.1.2.4 import java.util.LinkedList; 16 pnkfelix 1.1.2.4 import java.util.List; 17 pnkfelix 1.1.2.4 import java.util.Iterator; 18 pnkfelix 1.1.2.4 import java.util.Collections; 19 pnkfelix 1.1.2.1 20 pnkfelix 1.1.2.1 /** 21 pnkfelix 1.1.2.1 * <code>MaximalMunchCGG</code> finds an optimal tiling of 22 pnkfelix 1.1.2.1 * instructions on a Tree-IR. 23 pnkfelix 1.1.2.1 * 24 pnkfelix 1.1.2.1 * This Code Generator Generator produces Code Generators that use the 25 pnkfelix 1.1.2.1 * Maximal Munch algorithm to find an optimal tiling for an input 26 pnkfelix 1.1.2.1 * tree. See Appel "Modern Compiler Implementation in Java", Section 27 pnkfelix 1.1.2.1 * 9.1 for a description of Maximal Munch. 28 pnkfelix 1.1.2.1 * 29 pnkfelix 1.1.2.4 * 30 pnkfelix 1.1.2.1 * @author Felix S. Klock II <pnkfelix@mit.edu> 31 cananian 1.4 * @version $Id: MaximalMunchCGG.java,v 1.4 2002/04/10 03:06:53 cananian Exp $ */ 32 pnkfelix 1.1.2.1 public class MaximalMunchCGG extends CodeGeneratorGenerator { 33 pnkfelix 1.1.2.8 34 pnkfelix 1.1.2.8 35 cananian 1.1.2.42 private static final String TREE_ALIGN = "harpoon.IR.Tree.ALIGN"; 36 pnkfelix 1.1.2.8 private static final String TREE_BINOP = "harpoon.IR.Tree.BINOP"; 37 pnkfelix 1.1.2.8 private static final String TREE_CALL = "harpoon.IR.Tree.CALL"; 38 pnkfelix 1.1.2.8 private static final String TREE_CJUMP = "harpoon.IR.Tree.CJUMP"; 39 pnkfelix 1.1.2.8 private static final String TREE_CONST = "harpoon.IR.Tree.CONST"; 40 cananian 1.1.2.50 private static final String TREE_DATUM = "harpoon.IR.Tree.DATUM"; 41 jwhaley 1.1.2.62 private static final String TREE_EXPR = "harpoon.IR.Tree.EXPR"; 42 pnkfelix 1.1.2.8 private static final String TREE_JUMP = "harpoon.IR.Tree.JUMP"; 43 pnkfelix 1.1.2.8 private static final String TREE_LABEL = "harpoon.IR.Tree.LABEL"; 44 pnkfelix 1.1.2.8 private static final String TREE_MEM = "harpoon.IR.Tree.MEM"; 45 pnkfelix 1.1.2.23 private static final String TREE_METHOD = "harpoon.IR.Tree.METHOD"; 46 pnkfelix 1.1.2.8 private static final String TREE_MOVE = "harpoon.IR.Tree.MOVE"; 47 pnkfelix 1.1.2.8 private static final String TREE_NAME = "harpoon.IR.Tree.NAME"; 48 pnkfelix 1.1.2.8 private static final String TREE_NATIVECALL = "harpoon.IR.Tree.NATIVECALL"; 49 pnkfelix 1.1.2.8 private static final String TREE_OPER = "harpoon.IR.Tree.OPER"; 50 pnkfelix 1.1.2.8 private static final String TREE_RETURN = "harpoon.IR.Tree.RETURN"; 51 pnkfelix 1.1.2.8 private static final String TREE_SEQ = "harpoon.IR.Tree.SEQ"; 52 pnkfelix 1.1.2.26 private static final String TREE_SEGMENT = "harpoon.IR.Tree.SEGMENT"; 53 pnkfelix 1.1.2.8 private static final String TREE_TEMP = "harpoon.IR.Tree.TEMP"; 54 pnkfelix 1.1.2.8 private static final String TREE_THROW = "harpoon.IR.Tree.THROW"; 55 pnkfelix 1.1.2.8 private static final String TREE_UNOP = "harpoon.IR.Tree.UNOP"; 56 pnkfelix 1.1.2.8 57 cananian 1.1.2.34 private static final String TREE_BOP = "harpoon.IR.Tree.Bop"; 58 cananian 1.1.2.34 private static final String TREE_UOP = "harpoon.IR.Tree.Uop"; 59 cananian 1.1.2.34 60 pnkfelix 1.1.2.8 private static final String TREE_Tree = "harpoon.IR.Tree.Tree"; 61 pnkfelix 1.1.2.8 private static final String TREE_ExpList = "harpoon.IR.Tree.ExpList"; 62 pnkfelix 1.1.2.8 private static final String TREE_Exp = "harpoon.IR.Tree.Exp"; 63 pnkfelix 1.1.2.8 private static final String TREE_Stm = "harpoon.IR.Tree.Stm"; 64 pnkfelix 1.1.2.8 private static final String TREE_TreeVisitor = "harpoon.IR.Tree.TreeVisitor"; 65 cananian 1.1.2.60 private static final String TREE_Type = "harpoon.IR.Tree.Type"; 66 pnkfelix 1.1.2.8 67 pnkfelix 1.1.2.8 private static final String TEMP_Label = "harpoon.Temp.Label"; 68 pnkfelix 1.1.2.8 private static final String TEMP_Temp = "harpoon.Temp.Temp"; 69 cananian 1.1.2.59 private static final String TEMP_TempList = "harpoon.Temp.TempList"; 70 pnkfelix 1.1.2.8 71 pnkfelix 1.1.2.1 /** Creates a <code>MaximalMunchCGG</code>. 72 pnkfelix 1.1.2.1 <BR> <B>requires:</B> <OL> 73 pnkfelix 1.1.2.1 <LI> <code>s</code> follows the standard template for 74 pnkfelix 1.1.2.1 defining a machine specification. 75 pnkfelix 1.1.2.2 <LI> <code>className</code> is a legal Java identifier 76 pnkfelix 1.1.2.2 string for a class. 77 pnkfelix 1.1.2.1 <LI> For each node-type in the <code>Tree</code> IR, 78 pnkfelix 1.1.2.3 there exists a single-node tile pattern (TODO: I 79 pnkfelix 1.1.2.3 took this 'requirement' straight from Appel, but it 80 pnkfelix 1.1.2.3 can't REALLY be that strict. Find a tighter 81 pnkfelix 1.1.2.3 requirement that we can actually satisfy) 82 pnkfelix 1.1.2.1 <LI> if <code>s</code> contains Java statements that rely 83 pnkfelix 1.1.2.1 on knowledge about the class to be produced (such as 84 pnkfelix 1.1.2.1 a Constructor implementation) then the class named 85 pnkfelix 1.1.2.1 must match the <code>className</code> parameter. 86 pnkfelix 1.1.2.1 </OL> 87 pnkfelix 1.1.2.1 <BR> <B>effects:</B> Creates a new 88 pnkfelix 1.1.2.1 <code>MaximalMunchCGG</code> and associates the 89 pnkfelix 1.1.2.1 machine specification <code>s</code> with the newly 90 pnkfelix 1.1.2.1 constructed <code>MaximalMunchCGG</code>. 91 pnkfelix 1.1.2.2 @see <A HREF="doc-files/instr-selection-tool.html">Standard Specification Template</A> 92 pnkfelix 1.1.2.1 */ 93 pnkfelix 1.1.2.1 public MaximalMunchCGG(Spec s, String className) { 94 pnkfelix 1.1.2.1 super(s, className); 95 pnkfelix 1.1.2.55 } 96 pnkfelix 1.1.2.55 97 pnkfelix 1.1.2.55 protected String producedClassType() { 98 pnkfelix 1.1.2.55 return "harpoon.Backend.Generic.MaxMunchCG"; 99 pnkfelix 1.1.2.1 } 100 pnkfelix 1.1.2.1 101 cananian 1.1.2.35 /** Abstract interface for 'appending visitors' */ 102 cananian 1.1.2.35 static interface AppendingVisitor { 103 cananian 1.1.2.35 /** Append 's' to 'buf' with the proper indentation. */ 104 cananian 1.1.2.35 public void append(StringBuffer buf, String s); 105 cananian 1.1.2.35 } 106 cananian 1.1.2.35 107 pnkfelix 1.1.2.5 /** Sets up a series of checks to ensure all of the values in the 108 pnkfelix 1.1.2.5 visited statement are of the appropriate type. 109 pnkfelix 1.1.2.5 */ 110 cananian 1.1.2.35 static class TypeStmRecurse extends Spec.StmVisitor 111 cananian 1.1.2.35 implements AppendingVisitor { 112 pnkfelix 1.1.2.5 /** constantly updated boolean expression to match a tree's 113 pnkfelix 1.1.2.5 types. */ 114 pnkfelix 1.1.2.5 StringBuffer exp; 115 pnkfelix 1.1.2.5 116 pnkfelix 1.1.2.8 /** constantly updated set of statements to initialize the 117 pnkfelix 1.1.2.8 identifiers that the action statements will reference. */ 118 pnkfelix 1.1.2.8 StringBuffer initStms; 119 cananian 1.1.2.57 /** constantly updated set of statements to munch the rules' 120 cananian 1.1.2.57 * children if this rule matches. */ 121 cananian 1.1.2.57 StringBuffer munchStms; 122 pnkfelix 1.1.2.8 123 pnkfelix 1.1.2.5 /** constantly updated (and reset) with current statement 124 pnkfelix 1.1.2.5 prefix throughout recursive calls. */ 125 pnkfelix 1.1.2.5 String stmPrefix; 126 pnkfelix 1.1.2.5 127 pnkfelix 1.1.2.5 /** number of nodes "munched" by this so far. */ 128 pnkfelix 1.1.2.5 int degree; 129 pnkfelix 1.1.2.5 130 pnkfelix 1.1.2.5 /** Indentation. */ 131 pnkfelix 1.1.2.5 String indentPrefix; 132 pnkfelix 1.1.2.5 133 cananian 1.1.2.38 /** Type of root. */ 134 cananian 1.1.2.38 String rootType; 135 cananian 1.1.2.38 136 cananian 1.1.2.59 /** Helper function to merge a TypeExpRecurse into this one. */ 137 cananian 1.1.2.59 public void mergeStms(TypeExpRecurse r) { 138 cananian 1.1.2.59 initStms.append(r.initStms); 139 cananian 1.1.2.59 munchStms.append(r.munchStms); 140 cananian 1.1.2.59 } 141 cananian 1.1.2.59 /** helper function to prettify output */ 142 cananian 1.1.2.35 public void append(StringBuffer buf, String s) { 143 pnkfelix 1.1.2.8 buf.append(indentPrefix + s + "\n"); 144 pnkfelix 1.1.2.5 } 145 pnkfelix 1.1.2.5 146 pnkfelix 1.1.2.5 TypeStmRecurse(String stmPrefix, String indentPrefix) { 147 pnkfelix 1.1.2.5 // hack to make everything else additive 148 pnkfelix 1.1.2.5 exp = new StringBuffer("true\n"); 149 pnkfelix 1.1.2.8 initStms = new StringBuffer(); 150 cananian 1.1.2.57 munchStms = new StringBuffer(); 151 pnkfelix 1.1.2.5 degree = 0; 152 pnkfelix 1.1.2.5 this.stmPrefix = stmPrefix; 153 pnkfelix 1.1.2.5 this.indentPrefix = indentPrefix; 154 pnkfelix 1.1.2.5 } 155 pnkfelix 1.1.2.5 156 pnkfelix 1.1.2.5 public void visit(Spec.Stm s) { 157 cananian 1.3.2.1 assert false : "StmRecurse should never visit Stm: " + s + 158 cananian 1.3.2.1 " Class:" + s.getClass(); 159 pnkfelix 1.1.2.5 } 160 pnkfelix 1.1.2.23 161 pnkfelix 1.1.2.23 public void visit(Spec.StmMethod s) { 162 cananian 1.1.2.38 if (rootType==null) rootType=TREE_METHOD; 163 pnkfelix 1.1.2.23 degree++; 164 pnkfelix 1.1.2.23 165 pnkfelix 1.1.2.23 append(exp, "// check statement type"); 166 pnkfelix 1.1.2.23 append(exp, "&& " + stmPrefix + " instanceof " + TREE_METHOD + " "); 167 pnkfelix 1.1.2.23 168 cananian 1.1.2.45 // initialize params 169 cananian 1.1.2.57 append(munchStms, TEMP_Temp+"[] "+s.params+" = new "+TEMP_Temp+"["+ 170 cananian 1.1.2.54 "(("+TREE_METHOD+")"+stmPrefix+").getParamsLength()];"); 171 cananian 1.1.2.57 append(munchStms, "for (int _i_=0; _i_<"+s.params+".length; _i_++)"); 172 cananian 1.1.2.57 append(munchStms, " "+s.params+"[_i_] = munchExp("+ 173 cananian 1.1.2.54 "(("+TREE_METHOD+")"+stmPrefix+").getParams(_i_));"); 174 pnkfelix 1.1.2.23 } 175 pnkfelix 1.1.2.5 176 pnkfelix 1.1.2.5 public void visit(Spec.StmCall s) { 177 cananian 1.1.2.38 if (rootType==null) rootType=TREE_CALL; 178 pnkfelix 1.1.2.5 degree++; 179 pnkfelix 1.1.2.5 180 pnkfelix 1.1.2.8 append(exp, "// check statement type"); 181 pnkfelix 1.1.2.8 append(exp, "&& " + stmPrefix + " instanceof " + TREE_CALL +" "); 182 pnkfelix 1.1.2.8 183 pnkfelix 1.1.2.5 // look at func 184 pnkfelix 1.1.2.5 TypeExpRecurse r = new 185 duncan 1.1.2.49 TypeExpRecurse("(("+TREE_CALL+") " +stmPrefix +").getFunc()", 186 pnkfelix 1.1.2.5 indentPrefix + "\t"); 187 pnkfelix 1.1.2.5 s.func.accept(r); 188 pnkfelix 1.1.2.5 degree += r.degree; 189 pnkfelix 1.1.2.9 append(exp, "&& (" + r.exp.toString() +indentPrefix+")"); 190 cananian 1.1.2.59 mergeStms(r); 191 pnkfelix 1.1.2.5 192 cananian 1.1.2.46 // initialize retval 193 cananian 1.1.2.61 String retval = "(("+TREE_CALL+")"+stmPrefix + ").getRetval()"; 194 cananian 1.1.2.61 append(munchStms, TEMP_Temp+" "+s.retval+" = "+ 195 cananian 1.1.2.61 "("+retval+"==null) ? null : "+ 196 cananian 1.1.2.61 "munchExp("+retval+");"); 197 cananian 1.1.2.46 198 cananian 1.1.2.46 // initialize retex 199 cananian 1.1.2.61 String retex = "(("+TREE_CALL+")"+stmPrefix + ").getRetex()"; 200 cananian 1.1.2.61 append(munchStms, TEMP_Temp+" "+s.retex+" = "+ 201 cananian 1.1.2.61 "munchExp("+retex+");"); 202 cananian 1.1.2.46 203 cananian 1.1.2.46 // initialize handler 204 cananian 1.1.2.46 append(initStms, TEMP_Label+" "+s.handler+" = "+ 205 duncan 1.1.2.49 "(("+TREE_CALL+")"+stmPrefix + ").getHandler().label;"); 206 pnkfelix 1.1.2.16 207 cananian 1.1.2.37 // initialize arg list 208 cananian 1.1.2.57 append(munchStms, "/* munch argument ExpList into a TempList */"); 209 cananian 1.1.2.59 append(munchStms, TEMP_TempList+" "+ s.arglist + 210 cananian 1.1.2.59 " = new "+TEMP_TempList+"(null, null);"); 211 cananian 1.1.2.59 append(munchStms, "{ "+TEMP_TempList+" tl="+s.arglist+";"); 212 cananian 1.1.2.57 append(munchStms, " for ("+TREE_ExpList+" el"+ 213 duncan 1.1.2.49 " = (("+TREE_CALL+")"+stmPrefix+").getArgs();" + 214 cananian 1.1.2.37 " el!=null; el=el.tail, tl=tl.tail) "); 215 cananian 1.1.2.59 append(munchStms, " tl.tail = new "+TEMP_TempList+"("+ 216 cananian 1.1.2.37 "munchExp(el.head), null);"); 217 cananian 1.1.2.57 append(munchStms, "}"); 218 cananian 1.1.2.57 append(munchStms, s.arglist+" = "+s.arglist+".tail;"); 219 pnkfelix 1.1.2.5 } 220 pnkfelix 1.1.2.5 221 pnkfelix 1.1.2.5 public void visit(Spec.StmCjump s) { 222 cananian 1.1.2.38 if (rootType==null) rootType=TREE_CJUMP; 223 pnkfelix 1.1.2.5 degree++; 224 pnkfelix 1.1.2.5 225 pnkfelix 1.1.2.8 append(exp, "// check statement type"); 226 pnkfelix 1.1.2.15 append(exp, "&& (" + stmPrefix + " instanceof "+TREE_CJUMP+")"); 227 pnkfelix 1.1.2.5 228 pnkfelix 1.1.2.5 // look at test 229 pnkfelix 1.1.2.5 TypeExpRecurse r = new 230 duncan 1.1.2.49 TypeExpRecurse("(("+TREE_CJUMP+") " + stmPrefix + ").getTest()", 231 pnkfelix 1.1.2.5 indentPrefix + "\t"); 232 pnkfelix 1.1.2.5 s.test.accept(r); 233 pnkfelix 1.1.2.5 degree += r.degree; 234 pnkfelix 1.1.2.9 append(exp, "&& (" + r.exp.toString() + indentPrefix+")"); 235 cananian 1.1.2.59 mergeStms(r); 236 pnkfelix 1.1.2.8 237 pnkfelix 1.1.2.8 // code to initialize the target label identifiers so 238 pnkfelix 1.1.2.8 // that they can be referred to. 239 pnkfelix 1.1.2.15 append(initStms, TEMP_Label +" "+ s.f_label + 240 pnkfelix 1.1.2.15 " = (("+TREE_CJUMP+")"+stmPrefix+ 241 pnkfelix 1.1.2.15 ").iffalse;"); 242 pnkfelix 1.1.2.15 append(initStms, TEMP_Label +" "+ s.t_label + 243 pnkfelix 1.1.2.15 " = (("+TREE_CJUMP+")"+stmPrefix+ 244 pnkfelix 1.1.2.15 ").iftrue;"); 245 pnkfelix 1.1.2.8 246 pnkfelix 1.1.2.26 } 247 pnkfelix 1.1.2.26 248 pnkfelix 1.1.2.26 public void visit(Spec.StmData s) { 249 cananian 1.1.2.50 if (rootType==null) rootType=TREE_DATUM; 250 pnkfelix 1.1.2.26 degree++; 251 pnkfelix 1.1.2.26 252 pnkfelix 1.1.2.26 append(exp, "// check statement type"); 253 cananian 1.1.2.50 append(exp, "&& " + stmPrefix + " instanceof "+TREE_DATUM+""); 254 pnkfelix 1.1.2.26 255 pnkfelix 1.1.2.26 // look at exp 256 pnkfelix 1.1.2.26 TypeExpRecurse r = new 257 cananian 1.1.2.50 TypeExpRecurse("(("+TREE_DATUM+")"+ stmPrefix + ").getData()", 258 pnkfelix 1.1.2.26 indentPrefix + "\t"); 259 pnkfelix 1.1.2.26 s.data.accept(r); 260 pnkfelix 1.1.2.26 degree += r.degree; 261 pnkfelix 1.1.2.26 append(exp, "&& (" + r.exp.toString() + indentPrefix+")"); 262 cananian 1.1.2.59 mergeStms(r); 263 pnkfelix 1.1.2.26 } 264 pnkfelix 1.1.2.26 265 cananian 1.1.2.42 public void visit(Spec.StmAlign s) { 266 cananian 1.1.2.44 if (rootType==null) rootType=TREE_ALIGN; 267 cananian 1.1.2.42 degree++; 268 cananian 1.1.2.42 269 cananian 1.1.2.42 append(exp, "// check statement type"); 270 cananian 1.1.2.42 append(exp, "&& " + stmPrefix + " instanceof "+TREE_ALIGN+""); 271 cananian 1.1.2.42 272 cananian 1.1.2.42 s.alignment.accept(new Spec.LeafVisitor() { 273 cananian 1.1.2.42 public void visit(Spec.Leaf l) { 274 cananian 1.3.2.1 assert false : "Should never visit generic Leaf in StmAlign"; 275 cananian 1.1.2.42 } 276 cananian 1.1.2.42 public void visit(Spec.LeafNumber l) { 277 cananian 1.1.2.42 append(exp, "&& ((" + TREE_ALIGN + ")"+stmPrefix+ 278 cananian 1.1.2.42 ").alignment == " + l.number.intValue()); 279 cananian 1.1.2.42 } 280 cananian 1.1.2.42 public void visit(Spec.LeafId l) { 281 cananian 1.1.2.42 initStms.append("int " + l.id + " = ((" + TREE_ALIGN + ")"+ 282 cananian 1.1.2.42 stmPrefix+").alignment;"); 283 cananian 1.1.2.42 } 284 cananian 1.1.2.42 }); 285 cananian 1.1.2.42 } 286 cananian 1.1.2.42 287 pnkfelix 1.1.2.26 public void visit(Spec.StmSegment s) { 288 cananian 1.1.2.38 if (rootType==null) rootType=TREE_SEGMENT; 289 pnkfelix 1.1.2.26 degree++; 290 pnkfelix 1.1.2.26 291 pnkfelix 1.1.2.26 append(exp, "// check statement type"); 292 pnkfelix 1.1.2.26 append(exp, "&& " + stmPrefix + " instanceof "+TREE_SEGMENT+""); 293 pnkfelix 1.1.2.26 294 pnkfelix 1.1.2.26 s.segtype.accept(new Spec.LeafVisitor() { 295 pnkfelix 1.1.2.26 public void visit(Spec.Leaf l) { 296 cananian 1.3.2.1 assert false : "Should never visit generic Leaf in StmSegment"; 297 pnkfelix 1.1.2.26 } 298 pnkfelix 1.1.2.26 public void visit(Spec.LeafSegType l) { 299 pnkfelix 1.1.2.26 append(exp, "&& ((" + TREE_SEGMENT + ")"+stmPrefix+ 300 cananian 1.1.2.33 ").segtype == " + 301 cananian 1.1.2.33 TREE_SEGMENT + "." + SEGMENT.decode(l.segtype)); 302 pnkfelix 1.1.2.26 } 303 pnkfelix 1.1.2.26 public void visit(Spec.LeafId l) { 304 cananian 1.1.2.42 initStms.append("int "+l.id + " = ((" + TREE_SEGMENT + ")"+ 305 pnkfelix 1.1.2.27 stmPrefix+").segtype;"); 306 pnkfelix 1.1.2.26 } 307 pnkfelix 1.1.2.26 }); 308 pnkfelix 1.1.2.5 } 309 pnkfelix 1.1.2.5 310 pnkfelix 1.1.2.5 public void visit(Spec.StmExp s) { 311 jwhaley 1.1.2.62 if (rootType==null) rootType=TREE_EXPR; 312 pnkfelix 1.1.2.5 degree++; 313 pnkfelix 1.1.2.5 314 pnkfelix 1.1.2.8 append(exp, "// check statement type"); 315 jwhaley 1.1.2.62 append(exp, "&& " + stmPrefix + " instanceof "+TREE_EXPR+""); 316 pnkfelix 1.1.2.5 317 pnkfelix 1.1.2.5 // look at exp 318 pnkfelix 1.1.2.5 TypeExpRecurse r = new 319 jwhaley 1.1.2.62 TypeExpRecurse("(("+TREE_EXPR+")"+ stmPrefix + ").getExp()", 320 pnkfelix 1.1.2.5 indentPrefix + "\t"); 321 pnkfelix 1.1.2.5 s.exp.accept(r); 322 pnkfelix 1.1.2.5 degree += r.degree; 323 pnkfelix 1.1.2.9 append(exp, "&& (" + r.exp.toString() + indentPrefix+")"); 324 cananian 1.1.2.59 mergeStms(r); 325 pnkfelix 1.1.2.5 } 326 pnkfelix 1.1.2.5 327 pnkfelix 1.1.2.5 public void visit(Spec.StmJump s) { 328 cananian 1.1.2.38 if (rootType==null) rootType=TREE_JUMP; 329 pnkfelix 1.1.2.5 degree++; 330 pnkfelix 1.1.2.5 331 pnkfelix 1.1.2.8 append(exp, "// check statement type"); 332 pnkfelix 1.1.2.8 append(exp, "&& " + stmPrefix + " instanceof "+TREE_JUMP+""); 333 pnkfelix 1.1.2.5 334 pnkfelix 1.1.2.5 // look at exp 335 pnkfelix 1.1.2.5 TypeExpRecurse r = new 336 duncan 1.1.2.49 TypeExpRecurse("(("+TREE_JUMP+")" + stmPrefix + ").getExp()", 337 pnkfelix 1.1.2.5 indentPrefix + "\t"); 338 pnkfelix 1.1.2.5 s.exp.accept(r); 339 pnkfelix 1.1.2.5 degree += r.degree; 340 pnkfelix 1.1.2.9 append(exp, "&& (" + r.exp.toString() + indentPrefix+")"); 341 cananian 1.1.2.59 mergeStms(r); 342 pnkfelix 1.1.2.5 } 343 pnkfelix 1.1.2.5 344 pnkfelix 1.1.2.5 public void visit(Spec.StmLabel s) { 345 cananian 1.1.2.38 if (rootType==null) rootType=TREE_LABEL; 346 pnkfelix 1.1.2.5 degree++; 347 pnkfelix 1.1.2.5 348 pnkfelix 1.1.2.8 append(exp, "// check statement type"); 349 pnkfelix 1.1.2.8 append(exp, "&& " + stmPrefix + " instanceof "+TREE_LABEL+" "); 350 pnkfelix 1.1.2.8 351 pnkfelix 1.1.2.8 // code to initialize the target label identifiers so that 352 pnkfelix 1.1.2.8 // they can be referred to. 353 pnkfelix 1.1.2.15 append(initStms, "String " + s.name + 354 pnkfelix 1.1.2.15 " = (("+TREE_LABEL+")"+stmPrefix+ 355 pnkfelix 1.1.2.8 ").label.toString();\n"); 356 pnkfelix 1.1.2.5 } 357 pnkfelix 1.1.2.5 358 pnkfelix 1.1.2.5 public void visit(Spec.StmMove s) { 359 cananian 1.1.2.38 if (rootType==null) rootType=TREE_MOVE; 360 pnkfelix 1.1.2.5 degree++; 361 pnkfelix 1.1.2.5 362 pnkfelix 1.1.2.8 append(exp, "// check statement type"); 363 pnkfelix 1.1.2.8 append(exp, "&& " + stmPrefix + " instanceof "+TREE_MOVE+" "); 364 pnkfelix 1.1.2.24 365 cananian 1.1.2.36 String checkPrefix = "(("+TREE_MOVE+")" + stmPrefix + ")"; 366 cananian 1.1.2.35 appendTypeCheck(this, exp, checkPrefix, s.types); 367 pnkfelix 1.1.2.5 368 pnkfelix 1.1.2.5 // look at src 369 pnkfelix 1.1.2.5 TypeExpRecurse r = new 370 duncan 1.1.2.49 TypeExpRecurse("(("+TREE_MOVE+") " + stmPrefix + ").getSrc()", 371 pnkfelix 1.1.2.5 indentPrefix + "\t"); 372 pnkfelix 1.1.2.5 s.src.accept(r); 373 pnkfelix 1.1.2.5 degree += r.degree; 374 pnkfelix 1.1.2.8 append(exp, indentPrefix + "&& (" + r.exp.toString() + indentPrefix +")"); 375 cananian 1.1.2.59 mergeStms(r); 376 pnkfelix 1.1.2.5 377 pnkfelix 1.1.2.5 // look at dst 378 duncan 1.1.2.49 r = new TypeExpRecurse("(("+TREE_MOVE+") " + stmPrefix + ").getDst()", 379 pnkfelix 1.1.2.5 indentPrefix + "\t"); 380 pnkfelix 1.1.2.5 s.dst.accept(r); 381 pnkfelix 1.1.2.5 degree += r.degree; 382 pnkfelix 1.1.2.9 append(exp, "&& (" + r.exp.toString() + indentPrefix+")"); 383 cananian 1.1.2.59 mergeStms(r); 384 pnkfelix 1.1.2.5 } 385 pnkfelix 1.1.2.5 386 pnkfelix 1.1.2.5 public void visit(Spec.StmNativeCall s) { 387 cananian 1.1.2.38 if (rootType==null) rootType=TREE_NATIVECALL; 388 pnkfelix 1.1.2.5 degree++; 389 pnkfelix 1.1.2.5 390 pnkfelix 1.1.2.8 append(exp, "// check statement type"); 391 pnkfelix 1.1.2.8 append(exp, "&& " + stmPrefix + " instanceof "+TREE_NATIVECALL+""); 392 pnkfelix 1.1.2.5 393 pnkfelix 1.1.2.5 // look at func 394 pnkfelix 1.1.2.5 TypeExpRecurse r = new 395 duncan 1.1.2.49 TypeExpRecurse("(("+TREE_NATIVECALL+") " +stmPrefix +").getFunc()", 396 pnkfelix 1.1.2.5 indentPrefix + "\t"); 397 pnkfelix 1.1.2.5 s.func.accept(r); 398 pnkfelix 1.1.2.5 degree += r.degree; 399 pnkfelix 1.1.2.8 append(exp, indentPrefix + "&& (" + r.exp.toString() +indentPrefix+")"); 400 cananian 1.1.2.59 mergeStms(r); 401 pnkfelix 1.1.2.5 402 cananian 1.1.2.46 // initialize retval 403 cananian 1.1.2.61 String retval = "(("+TREE_NATIVECALL+")"+stmPrefix+").getRetval()"; 404 cananian 1.1.2.61 append(munchStms, TEMP_Temp+" "+s.retval+" = "+ 405 cananian 1.1.2.61 "("+retval+"==null) ? null : "+ 406 cananian 1.1.2.61 "munchExp("+retval+");"); 407 pnkfelix 1.1.2.8 408 pnkfelix 1.1.2.8 // initialize arg list 409 cananian 1.1.2.57 append(munchStms, "/* munch argument ExpList into a TempList */"); 410 cananian 1.1.2.59 append(munchStms, TEMP_TempList+" "+ s.arglist + 411 cananian 1.1.2.59 " = new "+TEMP_TempList+"(null, null);"); 412 cananian 1.1.2.59 append(munchStms, "{ "+TEMP_TempList+" tl="+s.arglist+";"); 413 cananian 1.1.2.57 append(munchStms, " for ("+TREE_ExpList+" el"+ 414 duncan 1.1.2.49 " = (("+TREE_NATIVECALL+")"+stmPrefix+").getArgs();" + 415 cananian 1.1.2.37 " el!=null; el=el.tail, tl=tl.tail) "); 416 cananian 1.1.2.59 append(munchStms, " tl.tail = new "+TEMP_TempList+"("+ 417 cananian 1.1.2.37 "munchExp(el.head), null);"); 418 cananian 1.1.2.57 append(munchStms, "}"); 419 cananian 1.1.2.57 append(munchStms, s.arglist+" = "+s.arglist+".tail;"); 420 pnkfelix 1.1.2.5 } 421 pnkfelix 1.1.2.5 422 pnkfelix 1.1.2.5 public void visit(Spec.StmReturn s) { 423 cananian 1.1.2.38 if (rootType==null) rootType=TREE_RETURN; 424 pnkfelix 1.1.2.5 degree++; 425 pnkfelix 1.1.2.5 426 pnkfelix 1.1.2.8 append(exp, "// check expression type"); 427 pnkfelix 1.1.2.8 append(exp, "&& " + stmPrefix + " instanceof "+TREE_RETURN+""); 428 pnkfelix 1.1.2.5 429 cananian 1.1.2.53 String checkPrefix = "(("+TREE_RETURN+")" + stmPrefix + ")"; 430 cananian 1.1.2.35 appendTypeCheck(this, exp, checkPrefix, s.types); 431 pnkfelix 1.1.2.5 432 pnkfelix 1.1.2.5 // look at exp 433 pnkfelix 1.1.2.5 TypeExpRecurse r = new 434 duncan 1.1.2.49 TypeExpRecurse("(("+TREE_RETURN+") " + stmPrefix + ").getRetval()", 435 pnkfelix 1.1.2.5 indentPrefix + "\t"); 436 pnkfelix 1.1.2.5 s.retval.accept(r); 437 pnkfelix 1.1.2.5 degree += r.degree; 438 pnkfelix 1.1.2.8 append(exp, indentPrefix + "&& (" + r.exp.toString() +indentPrefix+")"); 439 cananian 1.1.2.59 mergeStms(r); 440 pnkfelix 1.1.2.5 } 441 pnkfelix 1.1.2.5 442 pnkfelix 1.1.2.5 443 pnkfelix 1.1.2.5 public void visit(Spec.StmThrow s) { 444 cananian 1.1.2.38 if (rootType==null) rootType=TREE_THROW; 445 pnkfelix 1.1.2.5 degree++; 446 pnkfelix 1.1.2.5 447 pnkfelix 1.1.2.8 append(exp, "// check expression type"); 448 pnkfelix 1.1.2.8 append(exp, "&& " + stmPrefix + " instanceof "+TREE_THROW+""); 449 pnkfelix 1.1.2.5 450 pnkfelix 1.1.2.5 // look at exp 451 pnkfelix 1.1.2.5 TypeExpRecurse r = new 452 duncan 1.1.2.49 TypeExpRecurse("(("+TREE_THROW+") " + stmPrefix + ").getRetex()", 453 pnkfelix 1.1.2.5 indentPrefix + "\t"); 454 cananian 1.1.2.22 s.retex.accept(r); 455 pnkfelix 1.1.2.24 degree += r.degree; 456 pnkfelix 1.1.2.24 append(exp, indentPrefix + "&& (" + r.exp.toString() +indentPrefix+ ")"); 457 cananian 1.1.2.59 mergeStms(r); 458 pnkfelix 1.1.2.24 459 pnkfelix 1.1.2.24 // look at handler 460 pnkfelix 1.1.2.24 r = new 461 duncan 1.1.2.49 TypeExpRecurse("(("+TREE_THROW+") " + stmPrefix + ").getHandler()", 462 pnkfelix 1.1.2.24 indentPrefix + "\t"); 463 pnkfelix 1.1.2.24 s.handler.accept(r); 464 pnkfelix 1.1.2.5 degree += r.degree; 465 pnkfelix 1.1.2.8 append(exp, indentPrefix + "&& (" + r.exp.toString() +indentPrefix+ ")"); 466 cananian 1.1.2.59 mergeStms(r); 467 pnkfelix 1.1.2.5 } 468 pnkfelix 1.1.2.5 } 469 pnkfelix 1.1.2.5 470 pnkfelix 1.1.2.5 471 pnkfelix 1.1.2.5 472 pnkfelix 1.1.2.4 /** Sets up a series of checks to ensure all of the values 473 pnkfelix 1.1.2.4 in the visited expression are of the appropriate 474 pnkfelix 1.1.2.4 type. 475 pnkfelix 1.1.2.4 */ 476 cananian 1.1.2.35 static class TypeExpRecurse extends Spec.ExpVisitor 477 cananian 1.1.2.35 implements AppendingVisitor { 478 pnkfelix 1.1.2.5 /** constantly updated boolean expression to match a tree's 479 pnkfelix 1.1.2.5 types. */ 480 pnkfelix 1.1.2.4 StringBuffer exp; 481 pnkfelix 1.1.2.4 482 pnkfelix 1.1.2.8 /** constantly updated set of statements to initialize the 483 cananian 1.1.2.59 identifiers that the predicate expression will reference. */ 484 pnkfelix 1.1.2.8 StringBuffer initStms; 485 cananian 1.1.2.57 /** constantly updated set of statements to munch the rules' 486 cananian 1.1.2.57 * children if this rule matches. */ 487 cananian 1.1.2.57 StringBuffer munchStms; 488 pnkfelix 1.1.2.8 489 pnkfelix 1.1.2.5 /** constantly updated (and reset) with current expression 490 pnkfelix 1.1.2.5 prefix throughout recursive calls. */ 491 pnkfelix 1.1.2.4 String expPrefix; 492 pnkfelix 1.1.2.4 493 pnkfelix 1.1.2.4 /** number of nodes "munched" by this so far. */ 494 pnkfelix 1.1.2.4 int degree; 495 pnkfelix 1.1.2.4 496 pnkfelix 1.1.2.4 /** Indentation. */ 497 pnkfelix 1.1.2.4 String indentPrefix; 498 pnkfelix 1.1.2.4 499 cananian 1.1.2.38 /** Type of root. */ 500 cananian 1.1.2.38 String rootType; 501 cananian 1.1.2.38 502 cananian 1.1.2.59 /** Helper function to merge a TypeExpRecurse into this one. */ 503 cananian 1.1.2.59 public void mergeStms(TypeExpRecurse r) { 504 cananian 1.1.2.59 initStms.append(r.initStms); 505 cananian 1.1.2.59 munchStms.append(r.munchStms); 506 cananian 1.1.2.59 } 507 pnkfelix 1.1.2.8 /** Helper function to prettify resulting code. */ 508 cananian 1.1.2.35 public void append(StringBuffer buf, String s) { 509 pnkfelix 1.1.2.8 buf.append(indentPrefix + s +"\n"); 510 pnkfelix 1.1.2.4 } 511 pnkfelix 1.1.2.4 512 pnkfelix 1.1.2.4 TypeExpRecurse(String expPrefix, String indentPrefix) { 513 pnkfelix 1.1.2.5 // hack to make everything else additive 514 pnkfelix 1.1.2.5 exp = new StringBuffer("true\n"); 515 pnkfelix 1.1.2.8 initStms = new StringBuffer(); 516 cananian 1.1.2.57 munchStms = new StringBuffer(); 517 cananian 1.1.2.59 518 pnkfelix 1.1.2.4 degree = 0; 519 pnkfelix 1.1.2.4 this.expPrefix = expPrefix; 520 pnkfelix 1.1.2.4 this.indentPrefix = indentPrefix; 521 pnkfelix 1.1.2.4 } 522 pnkfelix 1.1.2.4 523 pnkfelix 1.1.2.4 public void visit(Spec.Exp e) { 524 cananian 1.3.2.1 assert false : "ExpRecurse should never visit Exp: "+e + 525 cananian 1.3.2.1 " Class: " + e.getClass(); 526 pnkfelix 1.1.2.4 } 527 pnkfelix 1.1.2.8 public void visit(final Spec.ExpBinop e) { 528 cananian 1.1.2.38 if (rootType==null) rootType=TREE_BINOP; 529 pnkfelix 1.1.2.4 degree++; 530 pnkfelix 1.1.2.4 531 pnkfelix 1.1.2.8 append(exp, "// check expression type"); 532 pnkfelix 1.1.2.8 append(exp, "&& " + expPrefix + " instanceof " + TREE_BINOP); 533 pnkfelix 1.1.2.4 534 pnkfelix 1.1.2.8 // My god, I can't tell if this visitor is good or bad for 535 pnkfelix 1.1.2.8 // understanding the code! 536 pnkfelix 1.1.2.8 e.opcode.accept(new Spec.LeafVisitor() { 537 pnkfelix 1.1.2.8 public void visit(Spec.Leaf l) { 538 cananian 1.3.2.1 assert false : "Should never visit generic Leaf in ExpBinop"; 539 pnkfelix 1.1.2.8 } 540 pnkfelix 1.1.2.8 public void visit(Spec.LeafOp l) { 541 pnkfelix 1.1.2.8 append(exp, "// check opcode"); 542 cananian 1.1.2.34 append(exp, "&& ((" + TREE_BINOP + ")" + expPrefix + ").op == " + TREE_BOP+"."+Bop.toString(l.op).toUpperCase()); 543 pnkfelix 1.1.2.8 } 544 pnkfelix 1.1.2.8 public void visit(Spec.LeafId l) { 545 pnkfelix 1.1.2.8 append(initStms, "int " + l.id + " = ((" + TREE_BINOP + ") " + 546 pnkfelix 1.1.2.8 expPrefix + ").op;"); 547 pnkfelix 1.1.2.8 } 548 pnkfelix 1.1.2.8 }); 549 pnkfelix 1.1.2.4 550 cananian 1.1.2.36 appendTypeCheck(this, exp, expPrefix, e.types); 551 pnkfelix 1.1.2.4 552 pnkfelix 1.1.2.4 // save state before outputing children-checking code 553 pnkfelix 1.1.2.4 String oldPrefix = expPrefix; 554 pnkfelix 1.1.2.4 String oldIndent = indentPrefix; 555 pnkfelix 1.1.2.4 556 pnkfelix 1.1.2.4 indentPrefix = oldIndent + "\t"; 557 pnkfelix 1.1.2.4 558 pnkfelix 1.1.2.8 append(exp, "// check left child"); 559 duncan 1.1.2.49 expPrefix = "((" + TREE_BINOP + ")" + oldPrefix + ").getLeft()"; 560 pnkfelix 1.1.2.4 e.left.accept(this); 561 pnkfelix 1.1.2.8 append(exp, "// check right child"); 562 duncan 1.1.2.49 expPrefix = "((" + TREE_BINOP + ")" + oldPrefix + ").getRight()"; 563 pnkfelix 1.1.2.4 e.right.accept(this); 564 pnkfelix 1.1.2.4 565 pnkfelix 1.1.2.4 // restore original state 566 pnkfelix 1.1.2.4 indentPrefix = oldIndent; 567 pnkfelix 1.1.2.4 expPrefix = oldPrefix; 568 pnkfelix 1.1.2.8 569 pnkfelix 1.1.2.4 } 570 pnkfelix 1.1.2.4 571 pnkfelix 1.1.2.4 public void visit(Spec.ExpConst e) { 572 cananian 1.1.2.38 if (rootType==null) rootType=TREE_CONST; 573 pnkfelix 1.1.2.4 degree++; 574 pnkfelix 1.1.2.4 575 pnkfelix 1.1.2.8 append(exp, "// check expression type"); 576 pnkfelix 1.1.2.8 append(exp, "&& " + expPrefix + " instanceof " + TREE_CONST + " "); 577 pnkfelix 1.1.2.4 578 cananian 1.1.2.36 appendTypeCheck(this, exp, expPrefix, e.types); 579 pnkfelix 1.1.2.8 580 pnkfelix 1.1.2.8 e.value.accept(new Spec.LeafVisitor() { 581 pnkfelix 1.1.2.8 public void visit(Spec.Leaf l) { 582 cananian 1.3.2.1 assert false : "Should never visit generic Leaf in ExpConst"; 583 pnkfelix 1.1.2.8 } 584 pnkfelix 1.1.2.8 public void visit(Spec.LeafId l) { 585 pnkfelix 1.1.2.10 append(initStms, "Number " + l.id + " = ((" + TREE_CONST + ") " + 586 pnkfelix 1.1.2.8 expPrefix + ").value;"); 587 pnkfelix 1.1.2.8 } 588 pnkfelix 1.1.2.8 public void visit(Spec.LeafNumber l) { 589 pnkfelix 1.1.2.8 append(exp, "// check that constant value matches"); 590 pnkfelix 1.1.2.8 append(exp, "&& ( " + expPrefix + ".isFloatingPoint()?"); 591 andyb 1.1.2.48 append(exp, "((" + TREE_CONST + ")" + expPrefix + ").value.doubleValue() == " + l.number.doubleValue() + ":"); 592 andyb 1.1.2.48 append(exp, "((" + TREE_CONST + ")" + expPrefix + ").value.longValue() == " + l.number.longValue() + ")"); 593 pnkfelix 1.1.2.8 } 594 pnkfelix 1.1.2.30 public void visit(Spec.LeafNull l) { 595 cananian 1.1.2.36 append(exp, "&& " + expPrefix + ".type() == Type.POINTER "); 596 pnkfelix 1.1.2.30 } 597 pnkfelix 1.1.2.8 }); 598 pnkfelix 1.1.2.4 } 599 pnkfelix 1.1.2.4 public void visit(Spec.ExpId e) { 600 pnkfelix 1.1.2.8 // don't increase the munch-factor (ie 601 pnkfelix 1.1.2.8 // 'degree') ( Spec.ExpId is strictly a way for a 602 pnkfelix 1.1.2.4 // specification to refer back to items in the parsed 603 pnkfelix 1.1.2.8 // tree) 604 pnkfelix 1.1.2.8 append(exp, "// no check needed for ExpId children"); 605 cananian 1.1.2.57 append(munchStms, TEMP_Temp +" "+ e.id +" = munchExp(" + expPrefix + "); "); 606 pnkfelix 1.1.2.4 return; 607 pnkfelix 1.1.2.4 } 608 pnkfelix 1.1.2.4 public void visit(Spec.ExpMem e) { 609 cananian 1.1.2.38 if (rootType==null) rootType=TREE_MEM; 610 pnkfelix 1.1.2.4 degree++; 611 pnkfelix 1.1.2.4 612 pnkfelix 1.1.2.8 append(exp, "// check expression type"); 613 pnkfelix 1.1.2.8 append(exp, "&& " + expPrefix + " instanceof " + TREE_MEM + " "); 614 pnkfelix 1.1.2.4 615 cananian 1.1.2.36 appendTypeCheck(this, exp, expPrefix, e.types); 616 pnkfelix 1.1.2.4 617 pnkfelix 1.1.2.4 // save state before outputing child-checking code 618 pnkfelix 1.1.2.4 String oldPrefix = expPrefix; 619 pnkfelix 1.1.2.4 String oldIndent = indentPrefix; 620 pnkfelix 1.1.2.4 621 pnkfelix 1.1.2.4 indentPrefix = oldIndent + "\t"; 622 pnkfelix 1.1.2.4 623 pnkfelix 1.1.2.8 append(exp, "// check child"); 624 duncan 1.1.2.49 expPrefix = "((" + TREE_MEM + ")" + oldPrefix + ").getExp()"; 625 pnkfelix 1.1.2.4 e.addr.accept(this); 626 pnkfelix 1.1.2.4 627 pnkfelix 1.1.2.4 // restore original state 628 pnkfelix 1.1.2.4 indentPrefix = oldIndent; 629 pnkfelix 1.1.2.4 expPrefix = oldPrefix; 630 pnkfelix 1.1.2.4 631 pnkfelix 1.1.2.4 } 632 pnkfelix 1.1.2.4 public void visit(Spec.ExpName e) { 633 cananian 1.1.2.38 if (rootType==null) rootType=TREE_NAME; 634 pnkfelix 1.1.2.4 degree++; 635 pnkfelix 1.1.2.4 636 pnkfelix 1.1.2.8 append(exp, "// check expression type"); 637 pnkfelix 1.1.2.15 append(exp, "&& " + expPrefix + " instanceof " + TREE_NAME + " "); 638 pnkfelix 1.1.2.8 639 pnkfelix 1.1.2.8 append(initStms, TEMP_Label +" "+ e.name + " = ((" +TREE_NAME + ")"+ 640 pnkfelix 1.1.2.8 expPrefix + ").label;"); 641 pnkfelix 1.1.2.4 642 pnkfelix 1.1.2.4 } 643 pnkfelix 1.1.2.4 public void visit(Spec.ExpTemp e) { 644 cananian 1.1.2.38 if (rootType==null) rootType=TREE_TEMP; 645 pnkfelix 1.1.2.4 degree++; 646 pnkfelix 1.1.2.4 647 pnkfelix 1.1.2.8 append(exp, "// check expression type"); 648 pnkfelix 1.1.2.15 append(exp, "&& " + expPrefix + " instanceof " + TREE_TEMP +" "); 649 pnkfelix 1.1.2.4 650 cananian 1.1.2.36 appendTypeCheck(this, exp, expPrefix, e.types); 651 pnkfelix 1.1.2.8 652 cananian 1.1.2.61 append(initStms, TEMP_Temp +" "+ e.name + " = "+ 653 cananian 1.1.2.61 "makeTemp((" +TREE_TEMP + ")"+expPrefix+", "+ 654 cananian 1.1.2.61 "inf.tempFactory());"); 655 pnkfelix 1.1.2.4 } 656 pnkfelix 1.1.2.4 public void visit(Spec.ExpUnop e) { 657 cananian 1.1.2.38 if (rootType==null) rootType=TREE_UNOP; 658 pnkfelix 1.1.2.4 degree++; 659 pnkfelix 1.1.2.4 660 pnkfelix 1.1.2.8 append(exp, "// check expression type"); 661 pnkfelix 1.1.2.8 append(exp, "&& " + expPrefix + " instanceof " + TREE_UNOP + " "); 662 pnkfelix 1.1.2.9 663 pnkfelix 1.1.2.9 e.opcode.accept(new Spec.LeafVisitor() { 664 pnkfelix 1.1.2.9 public void visit(Spec.Leaf l) { 665 cananian 1.3.2.1 assert false : "Should never visit generic Leaf in ExpUnop"; 666 pnkfelix 1.1.2.9 } 667 pnkfelix 1.1.2.9 public void visit(Spec.LeafOp l) { 668 pnkfelix 1.1.2.9 append(exp, "// check opcode"); 669 cananian 1.1.2.34 append(exp, "&& ((" + TREE_UNOP + ")" + expPrefix + ").op == " + TREE_UOP+"."+Uop.toString(l.op).toUpperCase()); 670 pnkfelix 1.1.2.9 } 671 pnkfelix 1.1.2.9 public void visit(Spec.LeafId l) { 672 pnkfelix 1.1.2.9 append(initStms, "int " + l.id + " = ((" + TREE_UNOP + ") " + 673 pnkfelix 1.1.2.9 expPrefix + ").op;"); 674 pnkfelix 1.1.2.9 } 675 pnkfelix 1.1.2.9 }); 676 pnkfelix 1.1.2.4 677 cananian 1.1.2.36 appendTypeCheck(this, exp, expPrefix, e.types); 678 pnkfelix 1.1.2.4 679 pnkfelix 1.1.2.4 // save state before outputting child-checking code 680 pnkfelix 1.1.2.4 String oldPrefix = expPrefix; 681 pnkfelix 1.1.2.4 String oldIndent = indentPrefix; 682 pnkfelix 1.1.2.4 683 pnkfelix 1.1.2.4 indentPrefix = oldIndent + "\t"; 684 pnkfelix 1.1.2.4 685 pnkfelix 1.1.2.8 append(exp, "// check child"); 686 duncan 1.1.2.49 expPrefix = "((" + TREE_UNOP + ")" + oldPrefix + ").getOperand()"; 687 pnkfelix 1.1.2.4 e.exp.accept(this); 688 pnkfelix 1.1.2.4 689 pnkfelix 1.1.2.4 // restore state 690 pnkfelix 1.1.2.4 expPrefix = oldPrefix; 691 pnkfelix 1.1.2.4 indentPrefix = oldIndent; 692 pnkfelix 1.1.2.4 } 693 pnkfelix 1.1.2.4 } 694 cananian 1.1.2.35 695 cananian 1.1.2.35 /** Append a type-checking expression to <code>exp</code>. */ 696 cananian 1.1.2.35 static void appendTypeCheck(AppendingVisitor av, StringBuffer exp, 697 cananian 1.1.2.36 String tree, Spec.TypeSet types) { 698 cananian 1.1.2.36 String PRECISELYTYPED="harpoon.IR.Tree.PreciselyTyped"; 699 cananian 1.1.2.35 av.append(exp, "// check operand types"); 700 cananian 1.1.2.35 boolean allowInt, allowLong, allowFloat, allowDouble, allowPointer; 701 cananian 1.1.2.35 allowDouble = types.contains(Type.DOUBLE); 702 cananian 1.1.2.35 allowFloat = types.contains(Type.FLOAT); 703 cananian 1.1.2.36 allowInt = types.contains(Type.INT); 704 cananian 1.1.2.35 allowLong = types.contains(Type.LONG); 705 cananian 1.1.2.35 allowPointer = types.contains(Type.POINTER); 706 cananian 1.1.2.35 av.append(exp, "&& ( "); 707 cananian 1.1.2.36 String checkPrefix = "\t" + tree + ".type() =="; 708 cananian 1.1.2.36 String precise = "(("+PRECISELYTYPED+")"+tree+")"; 709 cananian 1.1.2.35 if(allowDouble) av.append(exp, checkPrefix + " Type.DOUBLE ||"); 710 cananian 1.1.2.35 if(allowFloat) av.append(exp, checkPrefix + " Type.FLOAT ||"); 711 cananian 1.1.2.35 if(allowLong) av.append(exp, checkPrefix + " Type.LONG ||"); 712 cananian 1.1.2.35 if(allowPointer) av.append(exp, checkPrefix + " Type.POINTER ||"); 713 cananian 1.1.2.36 // INT is special because Small types are also INTs 714 cananian 1.1.2.36 if(allowInt) { 715 cananian 1.1.2.36 av.append(exp, "("+checkPrefix + " Type.INT && !"); 716 cananian 1.1.2.36 av.append(exp, " ("+tree+" instanceof "+PRECISELYTYPED+" &&"); 717 cananian 1.1.2.36 av.append(exp, " "+precise+".isSmall())) ||"); 718 cananian 1.1.2.36 } 719 cananian 1.1.2.36 // check for small types. 720 cananian 1.1.2.36 if(types.containsSmall()) { 721 cananian 1.1.2.36 av.append(exp, "\t(" + precise + ".isSmall() && ("); 722 cananian 1.1.2.36 av.append(exp, "\t "+precise + ".signed() ? ("); 723 cananian 1.1.2.36 for (int i=1; i<=32; i++) 724 cananian 1.1.2.36 if (types.containsSigned(i)) 725 cananian 1.1.2.36 av.append(exp, "\t "+precise+".bitwidth()=="+i+" ||"); 726 cananian 1.1.2.36 av.append(exp, "\t "+"false) : ("); 727 cananian 1.1.2.36 for (int i=1; i<=32; i++) 728 cananian 1.1.2.36 if (types.containsUnsigned(i)) 729 cananian 1.1.2.36 av.append(exp, "\t "+precise+".bitwidth()=="+i+" ||"); 730 cananian 1.1.2.36 av.append(exp, "\t "+"false) ) ) ||"); 731 cananian 1.1.2.36 } 732 cananian 1.1.2.35 av.append(exp, "\tfalse )"); 733 cananian 1.1.2.35 av.append(exp, "// end check operand types"); 734 cananian 1.1.2.35 } 735 pnkfelix 1.1.2.4 736 cananian 1.1.2.14 /**javac 1.1 sez this class (which is only used inside the 737 cananian 1.1.2.14 * outputSelectionMethod below) has to be out here, instead of 738 cananian 1.1.2.14 * inside the method. Actually, it doesn't specifically, but I can't 739 cananian 1.1.2.14 * figure out how to properly qualify the references to PredicateBuilder 740 cananian 1.1.2.14 * below to make them work right with javac 1.1, which gets confused 741 cananian 1.1.2.14 * over whose inner class PredicateBuilder is, actually. 742 cananian 1.1.2.14 * jikes likes fine, either way. go figure. [CSA] */ 743 cananian 1.1.2.14 static class PredicateBuilder extends Spec.DetailVisitor { 744 cananian 1.1.2.14 final StringBuffer predicate = new StringBuffer("true"); 745 cananian 1.1.2.14 public void visit(Spec.Detail d) { /* do nothing */ } 746 cananian 1.1.2.14 public void visit(Spec.DetailPredicate d) { 747 cananian 1.1.2.14 predicate.append("&& ("+d.predicate_string+")"); 748 cananian 1.1.2.14 } 749 cananian 1.1.2.14 } 750 cananian 1.1.2.60 /** Build 'extra' temps */ 751 cananian 1.1.2.60 static class ExtraBuilder extends Spec.DetailVisitor { 752 cananian 1.1.2.60 final StringBuffer extras = new StringBuffer(); 753 cananian 1.1.2.60 public void visit(Spec.Detail d) { /* do nothing */ } 754 cananian 1.1.2.60 public void visit(Spec.DetailExtra d) { 755 cananian 1.1.2.60 String clsname, tyname, isFloat, isDouble; 756 cananian 1.1.2.60 switch(d.type) { 757 cananian 1.1.2.60 case Type.INT: 758 cananian 1.1.2.60 tyname="INT"; clsname="Int"; 759 cananian 1.1.2.60 isFloat="false"; isDouble="false"; break; 760 cananian 1.1.2.60 case Type.LONG: 761 cananian 1.1.2.60 tyname="LONG"; clsname="Long"; 762 cananian 1.1.2.60 isFloat="false"; isDouble="true"; break; 763 cananian 1.1.2.60 case Type.FLOAT: 764 cananian 1.1.2.60 tyname="FLOAT"; clsname="Float"; 765 cananian 1.1.2.60 isFloat="true"; isDouble="false"; break; 766 cananian 1.1.2.60 case Type.DOUBLE: 767 cananian 1.1.2.60 tyname="DOUBLE"; clsname="Double"; 768 cananian 1.1.2.60 isFloat="true"; isDouble="true"; break; 769 cananian 1.1.2.60 case Type.POINTER: 770 cananian 1.1.2.60 tyname="POINTER"; clsname="Void"; 771 cananian 1.1.2.60 isFloat="false"; isDouble="frame.pointersAreLong()"; break; 772 cananian 1.1.2.60 default: throw new Error("unknown type!"); 773 cananian 1.1.2.60 } 774 cananian 1.1.2.60 for(Spec.IdList ilp = d.extras; ilp!=null; ilp=ilp.tail) { 775 cananian 1.1.2.60 extras.append("Temp "+ilp.head+" = frame.getTempBuilder()."+ 776 cananian 1.1.2.60 "makeTemp(new Typed() {\n"); 777 cananian 1.1.2.60 extras.append("\tpublic int type() { return "+ 778 cananian 1.1.2.60 TREE_Type+"."+tyname+"; }\n"); 779 cananian 1.1.2.60 extras.append("\tpublic boolean isFloatingPoint() { return "+ 780 cananian 1.1.2.60 isFloat+"; }\n"); 781 cananian 1.1.2.60 extras.append("\tpublic boolean isDoubleWord() { return "+ 782 cananian 1.1.2.60 isDouble+"; }\n"); 783 cananian 1.1.2.60 extras.append("}, inf.tempFactory() );\n"); 784 cananian 1.1.2.60 if (d.type != Type.POINTER) // pointers must be declared expl. 785 cananian 1.1.2.60 extras.append("declare("+ilp.head+", "+ 786 cananian 1.1.2.60 "HClass."+clsname+");\n"); 787 cananian 1.1.2.60 } 788 cananian 1.1.2.60 } 789 cananian 1.1.2.60 } 790 pnkfelix 1.1.2.1 /** Writes the Instruction Selection Method to <code>out</code>. 791 pnkfelix 1.1.2.1 <BR> <B>modifies:</B> <code>out</code> 792 pnkfelix 1.1.2.1 <BR> <B>effects:</B> 793 pnkfelix 1.1.2.1 Generates Java source for a MaximalMunch instruction 794 pnkfelix 1.1.2.2 selection method, not including method signature or 795 pnkfelix 1.1.2.2 surrounding braces. Outputs generated source to 796 pnkfelix 1.1.2.2 <code>out</code>. 797 pnkfelix 1.1.2.1 @param out Target output device for the Java source code. 798 pnkfelix 1.1.2.51 @param isData indicates if we're pattern matching code or data tables 799 pnkfelix 1.1.2.1 */ 800 pnkfelix 1.1.2.51 public void outputSelectionMethod(final PrintWriter out, 801 pnkfelix 1.1.2.51 final boolean isData) { 802 pnkfelix 1.1.2.4 // traverse 'this.spec' to acquire spec information 803 pnkfelix 1.1.2.8 final List expMatchActionPairs = new LinkedList(); // list of RuleTuple 804 pnkfelix 1.1.2.4 final List stmMatchActionPairs = new LinkedList(); 805 pnkfelix 1.1.2.4 806 pnkfelix 1.1.2.4 final String expArg = "expArg"; 807 pnkfelix 1.1.2.8 final String stmArg = "stmArg"; 808 pnkfelix 1.1.2.4 final String indent = "\t\t\t"; 809 pnkfelix 1.1.2.13 810 pnkfelix 1.1.2.52 811 pnkfelix 1.1.2.4 Spec.RuleVisitor srv = new Spec.RuleVisitor() { 812 pnkfelix 1.1.2.4 public void visit(Spec.Rule r) { 813 cananian 1.3.2.1 assert false : "SpecRuleVisitor should never visit Rule"; 814 pnkfelix 1.1.2.4 } 815 pnkfelix 1.1.2.4 public void visit(Spec.RuleStm r) { 816 pnkfelix 1.1.2.51 if (isData && !r.stm.canBeRootOfData()) { 817 pnkfelix 1.1.2.51 return; 818 pnkfelix 1.1.2.51 } 819 pnkfelix 1.1.2.51 820 pnkfelix 1.1.2.6 TypeStmRecurse recurse = 821 pnkfelix 1.1.2.8 new TypeStmRecurse(stmArg, indent + "\t"); 822 pnkfelix 1.1.2.6 r.stm.accept(recurse); 823 pnkfelix 1.1.2.4 824 pnkfelix 1.1.2.6 String typeCheck = recurse.exp.toString(); 825 pnkfelix 1.1.2.6 int munchFactor = recurse.degree; 826 pnkfelix 1.1.2.6 827 pnkfelix 1.1.2.13 PredicateBuilder makePred = new PredicateBuilder(); 828 pnkfelix 1.1.2.13 if (r.details!=null) r.details.accept(makePred); 829 cananian 1.1.2.60 ExtraBuilder makeExtra = new ExtraBuilder(); 830 cananian 1.1.2.60 if (r.details!=null) r.details.accept(makeExtra); 831 pnkfelix 1.1.2.13 832 pnkfelix 1.1.2.8 String matchStm = (indent + "if (" + typeCheck + indent + "){\n"+ 833 pnkfelix 1.1.2.9 recurse.initStms.toString() + 834 cananian 1.1.2.39 indent + recurse.rootType + " ROOT = (" + recurse.rootType + ") " + stmArg + ";\n" + 835 pnkfelix 1.1.2.13 indent + "\t_matched_ = " + makePred.predicate.toString()+";\n" + 836 cananian 1.1.2.39 ""); 837 pnkfelix 1.1.2.8 838 pnkfelix 1.1.2.8 //String matchStm = indent + "_matched_ = (" + typeCheck + indent + ");"; 839 pnkfelix 1.1.2.8 stmMatchActionPairs.add( new RuleTuple 840 pnkfelix 1.1.2.30 ( r.stm.toString(), 841 pnkfelix 1.1.2.30 matchStm, 842 cananian 1.1.2.57 indent + recurse.munchStms + "\n" + 843 cananian 1.1.2.60 // declare and assign %extra Temps 844 cananian 1.1.2.60 makeExtra.extras.toString()+ 845 pnkfelix 1.1.2.30 indent + r.action_str + 846 pnkfelix 1.1.2.30 indent + "return;" + 847 pnkfelix 1.1.2.30 indent + "}", null, 848 pnkfelix 1.1.2.30 recurse.degree ) ); 849 pnkfelix 1.1.2.4 } 850 pnkfelix 1.1.2.4 public void visit(Spec.RuleExp r) { 851 pnkfelix 1.1.2.52 if (isData) return; 852 pnkfelix 1.1.2.52 853 pnkfelix 1.1.2.4 TypeExpRecurse recurse = 854 pnkfelix 1.1.2.4 new TypeExpRecurse(expArg, indent + "\t"); 855 pnkfelix 1.1.2.4 r.exp.accept(recurse); 856 pnkfelix 1.1.2.4 857 pnkfelix 1.1.2.4 String typeCheck = recurse.exp.toString(); 858 pnkfelix 1.1.2.4 int munchFactor = recurse.degree; 859 pnkfelix 1.1.2.8 860 pnkfelix 1.1.2.13 PredicateBuilder makePred = new PredicateBuilder(); 861 pnkfelix 1.1.2.13 if (r.details!=null) r.details.accept(makePred); 862 cananian 1.1.2.60 ExtraBuilder makeExtra = new ExtraBuilder(); 863 cananian 1.1.2.60 if (r.details!=null) r.details.accept(makeExtra); 864 pnkfelix 1.1.2.8 865 pnkfelix 1.1.2.8 // TODO: add PREDICATE CHECK to end of matchStm 866 pnkfelix 1.1.2.47 String matchStm = 867 pnkfelix 1.1.2.47 (indent + "if ("+typeCheck+indent+"){\n" + 868 pnkfelix 1.1.2.47 recurse.initStms.toString() + indent + recurse.rootType + 869 pnkfelix 1.1.2.47 " ROOT = (" + recurse.rootType + ") " + expArg + ";\n" + 870 pnkfelix 1.1.2.47 indent + "\t_matched_ = "+makePred.predicate.toString()+";\n"); 871 pnkfelix 1.1.2.8 //String matchStm = indent + "_matched_ = (" + typeCheck + indent + ");"; 872 pnkfelix 1.1.2.8 expMatchActionPairs.add( new RuleTuple 873 pnkfelix 1.1.2.30 ( r.exp.toString(), 874 pnkfelix 1.1.2.47 matchStm, 875 cananian 1.1.2.57 recurse.munchStms.toString()+"\n"+ 876 pnkfelix 1.1.2.47 "Temp " + r.result_id + " = " + 877 pnkfelix 1.1.2.47 "frame.getTempBuilder()."+ 878 pnkfelix 1.1.2.51 "makeTemp( ROOT , inf.tempFactory());\n" + 879 pnkfelix 1.1.2.51 880 pnkfelix 1.1.2.51 // insert a type declare 881 pnkfelix 1.1.2.51 // for r.result.id 882 cananian 1.1.2.59 (isData?"":"clearDecl();\n"+ 883 cananian 1.1.2.59 "declare("+r.result_id+", "+ 884 cananian 1.1.2.59 "code.getTreeDerivation(), ROOT);"+ 885 cananian 1.1.2.59 "\n")+ 886 cananian 1.1.2.60 887 cananian 1.1.2.60 // declare and assign %extra Temps 888 cananian 1.1.2.60 makeExtra.extras.toString()+ 889 pnkfelix 1.1.2.51 890 pnkfelix 1.1.2.47 r.action_str + 891 pnkfelix 1.1.2.10 indent + "return " + r.result_id + ";\n" + 892 pnkfelix 1.1.2.30 indent + "}", r.result_id, 893 pnkfelix 1.1.2.30 recurse.degree ) ); 894 pnkfelix 1.1.2.4 895 pnkfelix 1.1.2.4 } 896 pnkfelix 1.1.2.4 897 pnkfelix 1.1.2.4 }; 898 pnkfelix 1.1.2.4 899 pnkfelix 1.1.2.4 Spec.RuleList list = spec.rules; 900 pnkfelix 1.1.2.4 while(list != null) { 901 pnkfelix 1.1.2.4 list.head.accept(srv); 902 pnkfelix 1.1.2.4 list = list.tail; 903 pnkfelix 1.1.2.4 } 904 pnkfelix 1.1.2.52 905 pnkfelix 1.1.2.4 906 cananian 1.1.2.61 /* 907 pnkfelix 1.1.2.52 Spec.TypeSet nonPtr = new Spec.TypeSet(); 908 pnkfelix 1.1.2.52 nonPtr.set(Type.INT); nonPtr.set(Type.LONG); 909 pnkfelix 1.1.2.52 nonPtr.set(Type.FLOAT); nonPtr.set(Type.DOUBLE); 910 pnkfelix 1.1.2.52 Spec.TypeSet ptr = new Spec.TypeSet(Type.POINTER); 911 pnkfelix 1.1.2.52 Spec.RuleExp tempRuleNP = new Spec.RuleExp 912 pnkfelix 1.1.2.52 (new Spec.ExpTemp(nonPtr, "t_orig"), "t_new", 913 pnkfelix 1.1.2.52 null, "Temp tt = frame.getTempBuilder().makeTemp( ROOT, inf.tempFactory());\n"); 914 pnkfelix 1.1.2.52 Spec.RuleExp tempRuleP = new Spec.RuleExp 915 pnkfelix 1.1.2.52 (new Spec.ExpTemp(ptr, "p_orig"),"p_new", 916 pnkfelix 1.1.2.52 null, "Temp pp = frame.getTempBuilder().makeTemp( ROOT, inf.tempFactory());\n"); 917 pnkfelix 1.1.2.52 918 pnkfelix 1.1.2.52 tempRuleNP.accept(srv); 919 pnkfelix 1.1.2.52 tempRuleP.accept(srv); 920 cananian 1.1.2.61 */ 921 pnkfelix 1.1.2.52 922 pnkfelix 1.1.2.8 Comparator compare = new RuleTupleComparator(); 923 pnkfelix 1.1.2.4 Collections.sort(expMatchActionPairs, compare); 924 pnkfelix 1.1.2.4 Collections.sort(stmMatchActionPairs, compare); 925 pnkfelix 1.1.2.4 926 pnkfelix 1.1.2.3 // Implement a recursive function by making a helper class to 927 pnkfelix 1.1.2.3 // visit the nodes 928 pnkfelix 1.1.2.9 out.println("\tfinal class CggVisitor extends "+TREE_TreeVisitor+" {"); 929 pnkfelix 1.1.2.3 930 pnkfelix 1.1.2.3 // for each rule for an exp we need to implement a 931 pnkfelix 1.1.2.3 // clause in munchExp() 932 pnkfelix 1.1.2.8 out.println("\t\t " + TEMP_Temp + " munchExp(" + TREE_Exp +" "+ expArg + ") {"); 933 pnkfelix 1.1.2.4 934 pnkfelix 1.1.2.4 out.println("\t\t\tboolean _matched_ = false;"); 935 cananian 1.1.2.58 out.println("\t\t\tclearDecl(); // reset temp type mappings"); 936 pnkfelix 1.1.2.4 937 pnkfelix 1.1.2.4 Iterator expPairsIter = expMatchActionPairs.iterator(); 938 pnkfelix 1.1.2.30 939 pnkfelix 1.1.2.30 int i = 1; 940 pnkfelix 1.1.2.30 941 pnkfelix 1.1.2.4 while(expPairsIter.hasNext()) { 942 pnkfelix 1.1.2.8 RuleTuple triplet = (RuleTuple) expPairsIter.next(); 943 pnkfelix 1.1.2.30 // out.println("System.out.println(\"Checkpoint Exp: "+(i++)+" \");"); 944 pnkfelix 1.1.2.30 out.println("\t\t\t\t /* " + triplet.rule + " */"); 945 pnkfelix 1.1.2.8 out.println(triplet.matchStms); 946 pnkfelix 1.1.2.25 out.println("\t\t\t\tif (_matched_) { // action code! degree: "+triplet.degree); 947 pnkfelix 1.1.2.4 out.println(triplet.actionStms); 948 pnkfelix 1.1.2.30 //out.println("\t\t\t\treturn " + triplet.resultId + ";"); 949 pnkfelix 1.1.2.4 out.println("\t\t\t}"); 950 pnkfelix 1.1.2.4 } 951 pnkfelix 1.1.2.8 952 cananian 1.3.2.1 out.println("\t\tassert false : \"Uh oh...\\n"+ 953 pnkfelix 1.1.2.20 "maximal munch didn't match anything...SPEC file\\n"+ 954 pnkfelix 1.1.2.20 "is not complete enough for this program\\n"+ 955 cananian 1.3.2.1 "Died on \"+prettyPrint("+expArg+")+\" in \" + prettyPrint(globalStmArg);"); 956 pnkfelix 1.1.2.10 out.println("\t\treturn null; // doesn't matter, we're dead if we didn't match..."); 957 cananian 1.1.2.40 out.println("\t\t } // end munchExp"); 958 pnkfelix 1.1.2.8 959 pnkfelix 1.1.2.25 out.println("\t"+TREE_Stm +" globalStmArg=null;"); 960 pnkfelix 1.1.2.4 961 pnkfelix 1.1.2.4 // for each rule for a statement we need to implement a 962 pnkfelix 1.1.2.4 // clause in munchStm() 963 pnkfelix 1.1.2.8 out.println("\t\t void munchStm("+TREE_Stm + " " + stmArg + ") {"); 964 pnkfelix 1.1.2.25 out.println("\t\t\t globalStmArg = " + stmArg +";"); 965 pnkfelix 1.1.2.6 out.println("\t\t\tboolean _matched_ = false;"); 966 cananian 1.1.2.58 out.println("\t\t\tclearDecl(); // reset temp type mappings"); 967 pnkfelix 1.1.2.6 968 pnkfelix 1.1.2.6 Iterator stmPairsIter = stmMatchActionPairs.iterator(); 969 pnkfelix 1.1.2.30 i=1; 970 pnkfelix 1.1.2.6 while(stmPairsIter.hasNext()) { 971 pnkfelix 1.1.2.8 RuleTuple triplet = (RuleTuple) stmPairsIter.next(); 972 pnkfelix 1.1.2.30 // out.println("System.out.println(\"Checkpoint Stm: "+(i++)+" \");"); 973 pnkfelix 1.1.2.30 out.println("\t\t\t\t /* " + triplet.rule + " */"); 974 pnkfelix 1.1.2.8 out.println(triplet.matchStms); 975 pnkfelix 1.1.2.25 out.println("\t\t\t\tif (_matched_) { // action code! : degree "+triplet.degree); 976 pnkfelix 1.1.2.6 out.println(triplet.actionStms); 977 pnkfelix 1.1.2.6 out.println("\t\t\t}"); 978 pnkfelix 1.1.2.6 } 979 pnkfelix 1.1.2.8 980 cananian 1.3.2.1 out.println("\t\tassert _matched_ : \"Uh oh...\\n"+ 981 cananian 1.1.2.40 "maximal munch didn't match anything...SPEC file\\n"+ 982 cananian 1.1.2.40 "is not complete enough for this program\\n"+ 983 cananian 1.3.2.1 "Died on \"+prettyPrint("+stmArg+")+\" in \" + prettyPrint(globalStmArg);"); 984 pnkfelix 1.1.2.11 out.println("\t\t} // end munchStm"); 985 pnkfelix 1.1.2.2 986 pnkfelix 1.1.2.17 out.println("\t\tpublic void visit("+TREE_Tree+" treee){"); 987 cananian 1.3.2.1 out.println("\t\t\tassert false : "+ 988 pnkfelix 1.1.2.11 "\"Should never visit generic " + TREE_Tree + 989 cananian 1.3.2.1 "in CggVisitor\";"); 990 pnkfelix 1.1.2.11 out.println("\t\t} // end visit("+TREE_Tree+")"); 991 pnkfelix 1.1.2.11 992 pnkfelix 1.1.2.17 out.println("\t\tpublic void visit("+TREE_Stm+" treee){"); 993 pnkfelix 1.1.2.21 out.println("\t\t\tdebug(\"munching \"+treee+\"\t\");"); 994 pnkfelix 1.1.2.17 out.println("\t\t\tmunchStm(treee);"); 995 pnkfelix 1.1.2.11 out.println("\t\t} // end visit("+TREE_Stm+")"); 996 pnkfelix 1.1.2.11 997 pnkfelix 1.1.2.31 out.println("\t\tpublic void visit("+TREE_SEQ+" treee){"); 998 duncan 1.1.2.49 out.println("\t\t\ttreee.getLeft().accept(this);"); 999 duncan 1.1.2.49 out.println("\t\t\ttreee.getRight().accept(this);"); 1000 pnkfelix 1.1.2.31 out.println("\t\t}"); 1001 pnkfelix 1.1.2.11 // BAD DOG! Don't implement visit(TREE_Exp)...we should never 1002 pnkfelix 1.1.2.11 // be munching those directly; only from calls to visit(TREE_Stm) 1003 pnkfelix 1.1.2.11 1004 pnkfelix 1.1.2.3 out.println("\t}"); // end CggVisitor 1005 pnkfelix 1.1.2.4 1006 pnkfelix 1.1.2.18 out.println("\tCggVisitor visitor = new CggVisitor();"); 1007 pnkfelix 1.1.2.18 out.println("\t"+TREE_Tree+" t = ("+TREE_Tree+") code.getRootElement();"); 1008 pnkfelix 1.1.2.31 1009 pnkfelix 1.1.2.31 //out.println("\twhile(t instanceof "+TREE_SEQ+") {"); 1010 pnkfelix 1.1.2.31 //out.println("\t\t"+TREE_SEQ+" seq = ("+TREE_SEQ+")t;"); 1011 duncan 1.1.2.49 //out.println("\t\tseq.getLeft().accept(visitor);"); 1012 duncan 1.1.2.49 //out.println("\t\tt=seq.getRight();"); 1013 pnkfelix 1.1.2.31 //out.println("\t}"); 1014 cananian 1.1.2.41 out.println("\tt.accept(visitor);"); 1015 pnkfelix 1.1.2.8 1016 cananian 1.1.2.59 out.println("\t\t\tclearDecl(); // reset temp type mappings"); 1017 pnkfelix 1.1.2.1 } 1018 pnkfelix 1.1.2.30 1019 pnkfelix 1.1.2.8 static class RuleTuple { 1020 pnkfelix 1.1.2.30 final String matchStms, actionStms, rule, resultId; 1021 pnkfelix 1.1.2.30 final int degree; 1022 pnkfelix 1.1.2.4 1023 pnkfelix 1.1.2.8 /** Constructs a new <code>RuleTuple</code>. 1024 pnkfelix 1.1.2.30 @param rule A <code>String</code> describing the rule 1025 pnkfelix 1.1.2.8 @param matchStms A series of Java statements which will set 1026 pnkfelix 1.1.2.8 _matched_ to TRUE if expression matches 1027 pnkfelix 1.1.2.8 and initialize variables that could be 1028 pnkfelix 1.1.2.8 references in 'actionStms'. Note that if the 1029 pnkfelix 1.1.2.8 matchStms start a new scope for the 1030 pnkfelix 1.1.2.8 variables to be initialized in (for 1031 pnkfelix 1.1.2.8 example, inside the then-clause of an 1032 pnkfelix 1.1.2.8 if-statement) then 'actionStms' must end 1033 pnkfelix 1.1.2.8 it, so that the RuleTuple is completely 1034 pnkfelix 1.1.2.8 selfcontained. 1035 pnkfelix 1.1.2.8 @param actionStms A series of Java statements to execute if 1036 pnkfelix 1.1.2.8 _matched_ == TRUE after 'matchExp' executes 1037 pnkfelix 1.1.2.30 @param resultId The identifier to return after 1038 pnkfelix 1.1.2.30 performing <code>actionStms</code>. 1039 pnkfelix 1.1.2.30 Will be <code>null</code> for 1040 pnkfelix 1.1.2.30 <code>RuleStm</code>s. 1041 pnkfelix 1.1.2.4 @param degree Number of nodes that this rule "eats" 1042 pnkfelix 1.1.2.30 */ 1043 pnkfelix 1.1.2.30 RuleTuple(String rule, String matchStms, String actionStms, String resultId, int degree) { 1044 pnkfelix 1.1.2.30 this.rule = rule; 1045 pnkfelix 1.1.2.8 this.matchStms = matchStms; 1046 pnkfelix 1.1.2.4 this.actionStms = actionStms; 1047 pnkfelix 1.1.2.4 this.degree = degree; 1048 pnkfelix 1.1.2.30 this.resultId = resultId; 1049 pnkfelix 1.1.2.4 } 1050 pnkfelix 1.1.2.4 } 1051 pnkfelix 1.1.2.4 1052 pnkfelix 1.1.2.8 static class RuleTupleComparator implements Comparator { 1053 pnkfelix 1.1.2.4 public int compare(Object o1, Object o2) { 1054 pnkfelix 1.1.2.8 RuleTuple r1 = (RuleTuple) o1; 1055 pnkfelix 1.1.2.8 RuleTuple r2 = (RuleTuple) o2; 1056 pnkfelix 1.1.2.25 return -(r1.degree - r2.degree); 1057 pnkfelix 1.1.2.4 } 1058 pnkfelix 1.1.2.4 } 1059 pnkfelix 1.1.2.4 1060 cananian 1.2 }