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      }