Package AGEvalSwipl

Source Code of AGEvalSwipl.CppGenerator

package AGEvalSwipl;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map.Entry;
import java.util.Vector;

import jpl.Term;
import jpl.Variable;

import aleGrammar.ALEParser;
import aleGrammar.ALEParser.ExtendedVertex;

import AGEval.AGEvaluator;
import AGEval.Class;
import AGEval.Function;
import AGEval.InvalidGrammarException;
import AGEval.Vertex;
import AGEvalSwipl.AGEvaluatorSwipl.Schedule;

public class CppGenerator extends BackendBase  implements Backend {

  public String replaceTypeVals(String body, ALEParser ast) { return body; }

 
    //TODO FIXME
  public static String typeStringToCppType (String type) {
    String lType = type.toLowerCase();
    if (lType.equals("color")) return "int";
    if (lType.equals("px")) return "int";
    if (lType.equals("float")) return "float";
    if (lType.equals("bool")) return "bool";
    if (lType.equals("int")) return "int";
    if (lType.equals("string")) return "const char *";
    if (lType.equals("std::string")) return "const char *";
    if (lType.equals("const char *")) return "const char *";
    if (lType.equals("taggedint")) return "Tagged<int>";
    if (lType.equals("taggedfloat")) return "Tagged<float>";
    return "int"; //"ExtraDataHandler::" + type;
  }
 
  public String nestedTernary(ALEParser.Case c, String lhsRaw, AGEval.Class cls, ALEParser ast) throws InvalidGrammarException {
      String res = "";
      if (!c.isElse) {   
        res += bindExpr(c.openBody, c.indexedVariables, cls, false, false, toAcc(lhsRaw, cls), ast);
        res += " ? ";
      } else {
        res += " : ";
      }
     
      for (ALEParser.Assignment asgn : c.assignments) {
        if (asgn._sink.equals(lhsRaw)) {
          res += "(" + bindExpr(asgn._indexedBody, asgn._variables, cls, false, false, toAcc(lhsRaw, cls), ast) + ")";
        }
      }
     
      for (ALEParser.Cond cnd : c.conditionals) {
        res += nestedTernary(cnd, lhsRaw, cls, ast);
      }
     
      return res;
    }
 
  //navigate cases until got assignment
  public String nestedTernary(ALEParser.Cond c, String lhsRaw, AGEval.Class cls, ALEParser ast) throws InvalidGrammarException {
    String res = "(";
    res += nestedTernary(c.testCase, lhsRaw, cls, ast);
    for (ALEParser.Case cs : c.elseifs) res += nestedTernary(cs, lhsRaw, cls, ast);
    res += nestedTernary(c.elseCase, lhsRaw, cls, ast);
    return res + ")";
  }
 
  public void addNestedConditionals (Schedule sched, HashMap<String, String> exprToCall, HashMap<String, String> exprPrinter) throws InvalidGrammarException {
      if (sched._ast.condsTop == null) return;     
    for (AGEval.Class cls : sched._aleg.classes) {
      if (sched._ast.condsTop.containsKey(cls)) {
          for (ALEParser.Cond cnd  : sched._ast.condsTop.get(cls)) {
            HashSet<String> nonReductSinks = new HashSet<String>();       
            HashSet<String> reductSinks = new HashSet<String>();
            Generator.gatherVariables(cnd, nonReductSinks, reductSinks);
            HashSet<String> sinks = new HashSet<String>();
            sinks.addAll(nonReductSinks);
            sinks.addAll(reductSinks);
                for (String lhsRaw : sinks) {
                  String lhs = lhsRaw.toLowerCase();
                  String loop = sched._ast.extendedClasses.get(cls).idToLoop.get(lhs);
                  if (loop == null) {
                    System.err.println("- loop cnd asgn, class " + cls.getName() + ": lhs " + lhs);
                    for (String opt : sched._ast.extendedClasses.get(cls).idToLoop.keySet()) {
                      System.err.println("  option: " + opt);
                    }
                    throw new InvalidGrammarException("could not find enclosing loop");
                  }                 
                 
                  boolean inLoop = !"".equals(sched._ast.extendedClasses.get(cls).idToLoop.get(lhs));
                  if (!inLoop) {                  
                    String fname = cls.getName().toLowerCase() + "_" + lhs;
                    String assign = lhsToAddress(lhsRaw, cls, sched._ast) + " = ";
                    String ternary = nestedTernary(cnd, lhsRaw, cls, sched._ast);
                    exprToCall.put(fname, assign + ternary);
                    exprPrinter.put(fname, "");
                  } else {
                    boolean isParentAttrib = !lhsRaw.contains("@") || lhsRaw.split("@")[0].equals("self");
                    String whoInit = cls.getName().toLowerCase() + "_" + lhsRaw.toLowerCase().replace("@", "_") + "_init";

                    String initLhs = isParentAttrib ?
                        lhsToAddress(lhsRaw, cls, sched._ast)
                        //: (Vertex.typeToString(Generator.lookupAttribute(lhsRaw, cls).myValueType) + " " + lhs.replace("@","_") + "_last");
                        : (typeStringToCppType(Generator.extendedGet(sched._ast, cls, lhsRaw).strType) + " " + lhs.replace("@","_") + "_last");

                     String dupeLhs = isParentAttrib ? "" : (lhs.replace("@","_") + "_last");

                    exprToCall.put(
                        whoInit,
                        initLhs + " = " + nestedTernaryLoopInit(sched.reductions, cnd, lhsRaw, cls, sched._ast));
                    exprPrinter.put(whoInit, "");
                    String whoStep = cls.getName().toLowerCase() + "_" + lhsRaw.toLowerCase().replace("@", "_") + "_step";
                    exprToCall.put(
                        whoStep,
                        lhsToAddress(lhsRaw, cls, sched._ast)
                        + " = " + nestedTernaryLoopStep(sched.reductions, cnd, lhsRaw, cls, sched._ast));
                    exprPrinter.put(whoStep, "");
                    if (!isParentAttrib) {
                      exprToCall.put(whoStep, exprToCall.get(whoStep) +
                          ";\n" + dupeLhs + " = " + lhsToAddress(lhsRaw, cls, sched._ast));
                      exprPrinter.put(whoStep, exprPrinter.get(whoStep) + "");    
                    }

                  }
                }
          }
      }
    }
  }
 


  public void addToplevels (AGEvaluator aleg, Schedule sched, Reductions reducts, HashMap<String, String> exprToCall, HashMap<String, String> exprPrinter) throws InvalidGrammarException {
    for (AGEval.Class cls : aleg.classes) {
      for (Function f : cls.getFunctions()) {
        String call =
          lhsToAddress(f.myDest, cls, sched._ast) + " = " +
          f.getName().replace(cls.getName().toLowerCase()+"_", cls.getName().toLowerCase()+"_toplevel_") + "(";
        String printArgs = "";
        boolean isFirst = true;
        for (String src : f.getStringSrcs()) {
          if (isFirst) isFirst = false;
          else call += ", ";
          call += lhsToAddress(src, cls, sched._ast);
          printArgs += "";//"#ifdef DEBUGY\n  cout << \"           " + src.toString() + ": \" << " + DataGenerator.lhsToAddress(src, cls) + " << endl;\n#endif //DEBUGY\n";
        }
        call += ")";
        //System.err.println("<+++ (" + f.getName() + "), " + call);
        //System.err.println("Adding nonloop top: " + f.getName());
        exprToCall.put(f.getName(), call);
       
        String printer = "";
        printer += "";//"#ifdef DEBUGY\n  cout << \"      "  + f.getName() + ": \" << " + DataGenerator.lhsToAddress(f.myDest, cls) + " << endl;\n#endif //DEBUGY\n";
        exprPrinter.put(f.getName(), printer + printArgs);
      }       
    } 
   
    for (ALEParser.Assignment asgn : sched._ast.assignments) {
      if (!"".equals(asgn.loopVar)) {
        AGEval.Class cls = asgn._class;
        String lhsRaw = asgn._sink;
        String lhs = lhsRaw.toLowerCase();
        //FIXME init assign loc..
            //String fname = cls.getName().toLowerCase() + "_" + lhs;
            //System.err.println("Adding loop: " + cls.getName().toLowerCase() + "_" + lhsRaw.toLowerCase().replace("@", "_") + "_init");
            //System.err.println("Adding loop: " + cls.getName().toLowerCase() + "_" + lhsRaw.toLowerCase().replace("@", "_") + "_step");
            boolean isParentAttrib = !lhsRaw.contains("@") || lhsRaw.split("@")[0].equals("self");
            String whoInit = cls.getName().toLowerCase() + "_" + lhsRaw.toLowerCase().replace("@", "_") + "_init";
            //String lhsInit = CppGenerator.lhsToAddress(isParentAttrib ? lhsRaw : (lhsRaw.replace("@", "_")+"_last"), cls);
           
            String initLhs = isParentAttrib ?
                lhsToAddress(lhsRaw, cls, sched._ast)
                : (typeStringToCppType(Generator.extendedGet(sched._ast, cls, lhsRaw).strType) + " " + lhs.replace("@","_") + "_last");
               
            String dupeLhs = isParentAttrib ? "" : (lhs.replace("@","_") + "_last");
               
              exprToCall.put(
                  whoInit,
                  initLhs + " = " + asgnLoopExpr(cls, reducts, asgn, lhsRaw, true, sched._ast));
              exprPrinter.put(whoInit, "");
            String whoStep = cls.getName().toLowerCase() + "_" + lhsRaw.toLowerCase().replace("@", "_") + "_step";
              exprToCall.put(
                  whoStep,
                  lhsToAddress(lhsRaw, cls, sched._ast)
                    + " = " + asgnLoopExpr(cls, reducts, asgn, lhsRaw, false, sched._ast));
              exprPrinter.put(whoStep, "");    
              if (!isParentAttrib) {
                exprToCall.put(whoStep, exprToCall.get(whoStep) +
                    ";\n" + dupeLhs + " = " + lhsToAddress(lhsRaw, cls, sched._ast));
                exprPrinter.put(whoStep, exprPrinter.get(whoStep) + "");    
              }
      }
    }
  }
 
  //============
 
  public String toAcc(String lhsRaw, AGEval.Class c) {
    String lhs = lhsRaw.toLowerCase();
    if (!lhs.contains("@")) return lhs + "_last";
    if (lhs.contains("self@")) return lhs.split("@")[1] + "_last";
    return lhs.replace("@", "_") + "_last";
  }
 
  public String bindExpr(String openBody, HashMap<String,String> indexedVariables, AGEval.Class cls, boolean allowStep, boolean replaceStep, String acc, ALEParser ast) throws InvalidGrammarException {
    String res = openBody;
    for (Entry<String, String> e : indexedVariables.entrySet()) {
      if (!allowStep && (e.getKey().equals("$acc") || e.getKey().contains("$i"))) {
        throw new InvalidGrammarException("reduction variables ($ identifiers) must be in loop steps, error binding expression "
            + openBody + " with " + e.getKey() + " == " + e.getValue());
      }
      if ("$acc".equals(e.getKey())) {
        if (replaceStep) {
          //init
          throw new InvalidGrammarException("$acc must be in loop steps, error binding expression "
              + openBody + " with " + e.getKey() + " == " + e.getValue());
        } else {
          //step
          res = res.replaceAll(e.getValue() + " ",
              acc.replace("$", "\\$") + " ");
          res = res.replaceAll(e.getValue() + "$", acc.replace("$", "\\$"+ " ");           
        }
      } else if (e.getKey().contains("$i")) {   
        if (replaceStep) {
          //FIXME init $i => final
          res = res.replaceAll(e.getValue() + " ", lhsToAddress(e.getKey(), cls, ast).replace("$", "\\$"+ " ");
          res = res.replaceAll(e.getValue() + "$", lhsToAddress(e.getKey(), cls, ast).replace("$", "\\$"+ " ");
          //FIXME data structure generation must provide (in case using more lax check than just isReduct...)
        } else {
          //step $i => child
          res = res.replaceAll(e.getValue() + " ", lhsToAddress(e.getKey(), cls, ast).replace("$", "\\$"+ " ");
          res = res.replaceAll(e.getValue() + "$", lhsToAddress(e.getKey(), cls, ast).replace("$", "\\$"+ " ");           
        }
      } else {
        res = res.replaceAll(e.getValue() + " ", lhsToAddress(e.getKey(), cls, ast).replace("$", "\\$"+ " ");
        res = res.replaceAll(e.getValue() + "$", lhsToAddress(e.getKey(), cls, ast).replace("$", "\\$"+ " ");
      }
    }
    return res;
  }

  //---

  public String nestedTernaryLoopStep(Reductions reducts, ALEParser.Case c, String lhsRaw, AGEval.Class cls, ALEParser ast) throws InvalidGrammarException {
    String res = "";
    if (!c.isElse) {   
      res += bindExpr(c.openBody, c.indexedVariables, cls, true, false, toAcc(lhsRaw, cls), ast);
      res += " ? ";
    } else {
      res += " : ";
    }
   
    for (ALEParser.Assignment asgn : c.assignments) {
      if (asgn._sink.equals(lhsRaw)) {
        res += asgnLoopExpr(cls, reducts, asgn, lhsRaw, false, ast);
      }
    }
   
    for (ALEParser.Cond cnd : c.conditionals) {
      res += nestedTernaryLoopStep(reducts, cnd, lhsRaw, cls, ast);
    }
   
    return res;
  }
 
  public String nestedTernaryLoopStep(Reductions reducts, ALEParser.Cond c, String lhsRaw, AGEval.Class cls, ALEParser ast) throws InvalidGrammarException {
    String res = "(";
    res += nestedTernaryLoopStep(reducts, c.testCase, lhsRaw, cls, ast);
    for (ALEParser.Case cs : c.elseifs) res += nestedTernaryLoopStep(reducts, cs, lhsRaw, cls, ast);
    res += nestedTernaryLoopStep(reducts, c.elseCase, lhsRaw, cls, ast);
    return res + ")";
  }
 
  //---
 

  // 
  public void checkInitable(Reductions reducts, AGEval.Class cls, HashMap<String,String> variables, String lhsRaw) throws InvalidGrammarException {
    System.err.println("checkInitable..");
/*
      for (String rawV : variables.keySet()) {
        if ("$acc".equals(rawV)            
          || (rawV.contains("$i") && !reducts.sinks.get(cls).contains(rawV.replace("$i", "")))) { //FIXME fixedpoint calc for better latter
          throw new InvalidGrammarException("non-reduction assignment to " + cls.getName() + "::" + lhsRaw
              + " potentially used as a last value ($$), with unscheduble initialization dependency on " + rawV);               
        }
      }
*/
  }
 
  public String asgnLoopExpr (AGEval.Class cls, Reductions reducts, ALEParser.Assignment asgn, String lhsRaw, boolean isInit, ALEParser ast) throws InvalidGrammarException {
    String res = "";
    if (asgn.isReduction) {
      res += "(" +
        bindExpr(
          isInit ? asgn.startBody : asgn.stepBody,
          isInit ? asgn.startVariables : asgn.stepVariables,
          cls, true, isInit, toAcc(lhsRaw, cls), ast) + ")";
    } else {
      if (reducts.accessedAsLast.get(cls).contains(lhsRaw.toLowerCase())) {
        checkInitable(reducts, cls, asgn._variables, lhsRaw);
      }
      res += "(" + bindExpr(asgn._indexedBody, asgn._variables, cls, true, isInit, toAcc(lhsRaw, cls), ast) + ")";
    }
   
    return res;
  }
  public String nestedTernaryLoopInit(Reductions reducts, ALEParser.Case c, String lhsRaw, AGEval.Class cls, ALEParser ast) throws InvalidGrammarException {
    String res = "";
    if (!c.isElse) {   
      checkInitable(reducts, cls, c.indexedVariables, lhsRaw);
      res += bindExpr(c.openBody, c.indexedVariables, cls, true, true, toAcc(lhsRaw, cls), ast);
      res += " ? ";
    } else {
      res += " : ";
    }
   
    for (ALEParser.Assignment asgn : c.assignments) {
      if (asgn._sink.equals(lhsRaw)) {
        res += asgnLoopExpr(cls, reducts, asgn, lhsRaw, true, ast);
      }
    }
   
    for (ALEParser.Cond cnd : c.conditionals) {
      res += nestedTernaryLoopInit(reducts, cnd, lhsRaw, cls, ast);
    }
   
    return res;
  }
 
  public String nestedTernaryLoopInit(Reductions reducts, ALEParser.Cond c, String lhsRaw, AGEval.Class cls, ALEParser ast) throws InvalidGrammarException {
    String res = "(";
    res += nestedTernaryLoopInit(reducts, c.testCase, lhsRaw, cls, ast);
    for (ALEParser.Case cs : c.elseifs) res += nestedTernaryLoopInit(reducts, cs, lhsRaw, cls, ast);
    res += nestedTernaryLoopInit(reducts, c.elseCase, lhsRaw, cls, ast);
    return res + ")";
  }
 
  //-----
 
 
 
 
 
  //============
 
 
 
 
 
 
 
 
 
 
 
 
 
  public String visitDispatcher(int visit, AGEvaluator aleg, HashSet<AGEval.Class>buIns, HashSet<AGEval.Class>bus) {
    HashSet<AGEval.Class> inIns = getInIns(aleg, bus, buIns);
   
    String res =
      "bool visit_"+ visit + " (bool isGlobalCall, VISITPARAMS) {\n" +
      "  switch (s.data.parseData.display) {\n";
    for (AGEval.Class cls : aleg.classes) {
      res += "    case ExtraDataHandler::TOK_" + cls.getName().toUpperCase() + ":\n";
   
      if (buIns != null && buIns.contains(cls)) { /* is inorder and may have bu parent: will be called 2x, need to dynamically filter out global variant*/
        res +=
        "        if (isGlobalCall && (SPARENT != NULL) && isInorder(SPARENT, " + visit + ")) return true;\n";       
      } else if (buIns != null && inIns.contains(cls))  {
        res +=
        "        if (isGlobalCall && (SPARENT != NULL) ) return true;\n";                 
      }
      res +=
        "      return visit_" + cls.getName().toLowerCase() + "_" + visit + "(VISITARGS(s, root, SPARENT));\n";
    }
    res += "  }\n";
    res += "  return true;\n}\n";
    return res;
  }
  public String visitDispatchers(int visits, AGEvaluator aleg, Vector<HashSet<AGEval.Class>> buSubInorderBuIns, Vector<HashSet<AGEval.Class>> buSubInorderBus) {
    String res = "";
    for (int i = 0; i < visits; i++) res += visitDispatcher(i, aleg, buSubInorderBuIns.get(i), buSubInorderBus.get(i));
    return res;
  }
 
  /*
  private static String getFieldByTag(AGEvaluator aleg, String prop, String type) {
  String res = "";
  res +=
    type + " get_dynamic_field_" + prop + "(SNode *n) {\n" +
    "  switch (n->data.computeData.tag) {\n";
  for (AGEval.Class cls : aleg.classes) {
    if (cls.getPrivAttributes().containsKey(prop) || cls.getPubAttributes().containsKey(prop)) {
      res += "    case aletags::TAG_" + cls.getName().toUpperCase() + ":\n" +
        "      n->data.computeData.classData.ExtraSub" + cls.getName() + "." + prop + ";\n" +
        "      break;\n";       
    }
  }
  res +=
    "    default: \n" +
    "      cout << \"no property " + prop + " to get\" << end;\n" +
    "      exit(1);\n" +
    "  }\n" +
    "}\n";
  return res; 
  } 
 
  private static String getFieldsByTag(AGEvaluator aleg) throws InvalidGrammarException {
    String res = "";
    HashMap<String, String> fields = new HashMap<String, String>();  
    for (AGEval.Class cls : aleg.classes) {
      for (String attr : cls.getPubAttributes().keySet()) {
        String type = Vertex.typeToString(cls.getPubAttributes().get(attr));
        if (fields.containsKey(attr)) {
          if (!fields.get(attr).equals(type)) throw new InvalidGrammarException("For now, require all same name attributes to be of same type");
          continue;
        }
        fields.put(attr, type);       
      }
    }
   
    for (String attr : fields.keySet()) {
      String type = fields.get(attr);
      res += getFieldByTag(aleg, attr, type);
    }
   
    return res;
  }
    */

 
  public String lhsToAddress (String lhs, Class cls, ALEParser ast) throws InvalidGrammarException {
      boolean isParent;
      boolean isParseData;
      String child;
      String prop;
      if (lhs.split("@").length == 2) {
        child = lhs.split("@")[0];
        isParent = child.equals("self");
        prop = lhs.split("@")[1];       
//        if (prop.contains("$") && child.equals("self")) {
//          System.err.println("CppGen: Cannot use intra-reduction accessors (self$$, ...), caught on use " + child + " in " + lhs);
//          //throw new InvalidGrammarException("Cannot use intra-reduction accessors (self$$, ...), caught on use " + child + " in " + lhs);
//        }
      } else {
        child = ""; //silly Java
        isParent = true;
        prop = lhs;
      }
      String propClean = prop.toLowerCase();           
      try {
        if (propClean.contains("_init") || propClean.contains("_last")) { //loop vars
          isParseData = false;
        } else {
          ExtendedVertex v = Generator.extendedGet(ast, cls, lhs.replace("$$", "").replace("$i", "").replace("$-", ""));         
          if (v.isInput) throw new InvalidGrammarException("Accessing parse data as lhs: " + cls.getName() + "::" + lhs);
          else isParseData = false;
        }
      } catch (InvalidGrammarException e) {
        e.printStackTrace();
        isParseData = false;
      }
      if (isParent) {
        String base = isParseData ? ("parseData.genData.extraParse" + cls.getName()) : ("computeData.classData.Sub" + cls.getName());
        return base + "." + (isParseData ? "fld_" : "") + prop.toLowerCase();
      } else if (Generator.childrenContains(ast.extendedClasses.get(cls).multiChildren.keySet(), child)) {
        if (isParseData) return "loopChild->data.parseData.genData.extraParse" + cls.getChildByName(child).getName() + ".fld_" + propClean;
        else return "loopChild->data.computeData.classData.Sub" + cls.getChildByName(child) + "." + propClean;       
      } else {
        String base =
          "#if defined(VERYSMALLTREEPOINTERS)\n" +
          "(&s + s.distanceToLeftmostChild + computeData.classData.Sub" + cls.getName() + ".child_" + child + ")\n" +
          "#elif defined(SMALLTREEPOINTERS)\n" +
          "(s.leftmostChild + computeData.classData.Sub" + cls.getName() + ".child_" + child + ")\n" +
          "#else\n" +
          "(computeData.classData.Sub" + cls.getName() + ".child_" + child + ")\n" +
          "#endif // ptrs\n";
        if (isParseData)
          return base + "->data.parseData.genData.extraParse" + cls.getChildByName(child).getName() + ".fld_" + propClean;
        else
          return base + "->data.computeData.classData.Sub" + cls.getChildByName(child) + "." + propClean;
      }
     
   
  }
 
public static String assignAliases(AGEval.Class c, ALEParser ast) {
  if (c.getChildMappings() == null) throw new NullPointerException();
  if (ast.extendedClasses == null) throw new NullPointerException();
  if (ast.extendedClasses.get(c) == null) {
    System.err.println("EC has no class: " + c.getName());
    for (AGEval.IFace s : ast.extendedClasses.keySet()) {
      System.err.println("  option: "+ s.getName() + " => " + (ast.extendedClasses.get(s) == null ? "null" : "val"));
      if (s.getName().equals(c.getName())) {
        System.err.println("    same name!");
        System.err.println("    " + (s == c ? " same key " : " diff key"));
      }
    }
    throw new NullPointerException();
  }
    int numSingle = c.getChildMappings().size() - ast.extendedClasses.get(c).multiChildren.keySet().size();
 
    String res = "static void assignAliases_" + c.getName() + " (VISITPARAMS) {\n";
   
    if (numSingle == 0 && ast.extendedClasses.get(c).multiChildren.keySet().size() == 0) return res + "}\n";
   
    for (String n : ast.extendedClasses.get(c).multiChildren.keySet())
      res += "  s.data.computeData.classData.Sub" + c.getName() + ".child_" + n.toLowerCase() + "_count = 0;\n";
       
    res +=
      "#if defined(SMALLTREEPOINTERS) || defined(VERYSMALLTREEPOINTERS)\n" +
      "  PTRBACKINGTYPE __assignAliasesOffset = 0;\n"+//s.distanceToLeftmostChild;\n" +
      "#endif //small / vsmall ptrs\n" +
      "#ifdef DEBUGY\n  int found = 0;\n#endif //DEBUGY\n" +
      "  SFORLOOP(child, s) {\n" +
      "    switch(child->data.parseData.refname) {\n";
    for (String n : c.getChildMappings().keySet()) { //skip multichildren maps (instead dyn lookup)      
      if (ast.extendedClasses.get(c).multiChildren.containsKey(n)) {
        res +=
          "      case ExtraDataHandler::TOK_" + n.toUpperCase() + ":\n" +
          "        s.data.computeData.classData.Sub" + c.getName() + ".child_"+ n.toLowerCase() + "_count++;\n" +
          "#if defined(DEBUGY)\n" +
          "        cout << \"  found " + n + " alias\" << endl;\n" +
          "#endif //DEBUGY\n" +                 
          "#if defined(DEBUGY) && defined(VERYSMALLTREEPOINTERS)\n" +
          "        if (child != (&s + s.distanceToLeftmostChild + __assignAliasesOffset)) {\n" +
          "          cout << \"failed pointer compression/decompression \" << endl; exit(1); \n" +
          "        }\n" +
          "#endif //DEBUGY && VS\n" +       
          "        break; \n";
      } else {
        res +=
          "      case ExtraDataHandler::TOK_" + n.toUpperCase() + ":\n" +
          "#if defined(VERYSMALLTREEPOINTERS)\n" +
          "        s.data.computeData.classData.Sub" + c.getName() + ".child_"+ n + " = __assignAliasesOffset;\n" +
          "#elif defined(SMALLTREEPOINTERS)\n" +
          "        s.data.computeData.classData.Sub" + c.getName() + ".child_"+ n + " = __assignAliasesOffset;\n" +
          "#else\n" +
          "        s.data.computeData.classData.Sub" + c.getName() + ".child_"+ n + " = child;\n" +
          "#endif //ptrs\n" +
          "#if defined(DEBUGY)\n" +
          "        found++;\n" +
          "#endif //DEBUGY\n" +       
          "#if defined(DEBUGY) && defined(VERYSMALLTREEPOINTERS)\n" +
          "        if (child != (&s + s.distanceToLeftmostChild + __assignAliasesOffset)) {\n" +
          "          cout << \"failed pointer compression/decompression \" << endl; exit(1); \n" +
          "        }\n" +
          "        cout << \"  found multi " + n + " alias\" << endl;\n" +
          "#endif //DEBUGY\n" +       
          "        break; \n";
      }
    }
   
    String multiChecks;
    /*
    if (ast.extendedClasses.get(c).multiChildren.size() > 0) {
      multiChecks =
        "#ifdef DEBUGY\n" +
        "        switch(child->data.parseData.displayname) {\n";
      for (String iface : ast.extendedClasses.get(c).multiChildren.keySet())
        multiChecks +=
          "          case ExtraDataHandler::TOK_" + iface.toUpperCase() + ":\n" +
          "            break;\n";       
      multiChecks +=
        "          default: \n" +
        "            cout << \"unknown refname/display type in " + c.getName() +
        ": \" << child->data.parseData.refname << \"/\" << child->data.parseData.displayname << endl;\n" +
        "            exit(1);\n" +
        "        }\n" +
        "#endif //DEBUGY\n";

    } else {
    */
      multiChecks =      
        "#ifdef DEBUGY\n" +
        "        cout << \"unknown refname type in " + c.getName() + ": \" << child->data.parseData.refname << endl;\n" +
        "        exit(1);\n" +
        "#endif //DEBUGY\n";     
    //}

    res +=
      "      default: \n" +
      multiChecks +
      "        break;\n" +
      "    }\n" +
      "#if defined(SMALLTREEPOINTERS) || defined(VERYSMALLTREEPOINTERS)\n" +
      "    __assignAliasesOffset++;\n" +
      "#endif //small or vsmall pts\n" +
      "  } SFORLOOPEND(child, s);\n" +
      "#ifdef DEBUGY\n" +
      "  if (found != " + numSingle + ") {\n" +
      "    cout << \"Did not find expected singleton childs for class " + c.getName() + "; found \" << found << \" of " + numSingle + "\" << endl;\n" +
      "    exit(1);\n" +
      "  }\n" +
      "#endif //DEBUGY\n";
    res += "}\n";
    return res;
  }


  public static String genInterfaceHeaderFields (AGEval.IFace i, HashMap<AGEval.IFace, ALEParser.ExtendedClass> extendedClasses) {
    ALEParser.ExtendedClass ei = extendedClasses.get(i);
    String res = "";
    //sortedPubs = i.getPubAttributes().keySet().toArray(sortedPubs);
    HashSet<String> pubs = new HashSet<String>();
    for (Entry<String, ExtendedVertex> v : ei.extendedVertices.entrySet())  {
      if (!v.getValue().isInput) pubs.add(v.getKey());
    }
    String[] sortedPubs = {};
    sortedPubs = pubs.toArray(sortedPubs);
    Arrays.sort(sortedPubs);
    int counter = 0;
    for (String n : sortedPubs) {
      while (ei.positionedVariables.containsKey(new Integer(counter))) {
        String prop = ei.positionedVariables.get(new Integer(counter));
        //FIXME type lookup for extended types
        res += "  " + typeStringToCppType(ei.extendedVertices.get(prop).strType) + " " + prop + ";\n";
        counter++;
      }
      if (!ei.positionedVariables.containsValue(n)) {           
        //FIXME type lookup for extended types
        res += "  " + typeStringToCppType(ei.extendedVertices.get(n).strType.replace("color", "int"))  + " " + n.toLowerCase() + ";\n";
        counter++;
      }
    }
    return res;
  }
 
  public static String interfaceHeader (AGEval.IFace i, HashMap<AGEval.IFace, ALEParser.ExtendedClass> extendedClasses) {
    String res = "struct ExtraSub" + i.getName() + " {\n";
    res += genInterfaceHeaderFields(i, extendedClasses);
    res += "};\n";   
    return res;
  }
 
  public static String classHeader (AGEval.Class c, HashMap<AGEval.IFace, ALEParser.ExtendedClass> extendedClasses, Schedule sched) throws InvalidGrammarException {
    //ALEParser.ExtendedClass ei = extendedClasses.get(c.getInterface());
    String res = "struct ExtraSub" + c.getName() + " {\n";
    res += genInterfaceHeaderFields(c.getInterface(), extendedClasses);
    for (String n : c.getChildMappings().keySet()) {
      if (extendedClasses.get(c).multiChildren.containsKey(n)) res += "  PTRBACKINGTYPE child_" + n.toLowerCase() + "_count;\n";
      else res += "  PTRBACKINGTYPE child_" + n.toLowerCase() + ";\n";
    }
    for (String n : c.getPrivAttributes().keySet())
      res += "  " + typeStringToCppType(Vertex.typeToString(c.getPrivAttributes().get(n))) + " " + n.toLowerCase() + ";\n";

   
    for (String sink : sched.reductions.sinks.get(c)) {
      String type = typeStringToCppType(Generator.extendedGet(sched._ast, c, sink).strType);
     
      if (!sink.contains("@") || sink.contains("self@")) {
        String propClean = AGEvaluatorSwipl.attribName(sink).toLowerCase();
        res += "  " + type + " " + propClean + "_init;\n";
        res += "  " + type + " " + propClean + "_last;\n";
      } else {
        String propClean = sink.replace("@", "_").toLowerCase();
        res += "  " + type + " " + propClean + "_init;\n";
        res += "  " + type + " " + propClean + "_last;\n";
      }
    }
    /*
    for (String f : reducts) {
        if (!f.contains("@") || f.contains("self@")) continue;   
        res += "  " + Vertex.typeToString(Generator.lookupAttribute(f, c).myValueType) + " " + f.replace("@", "_") + "_last;\n";
    }
    */
    //res += assignAliases(c);
    res += "};\n";   
    return res;
  }
 
  public static String classesHeader(ALEParser ast, int numVisits, Schedule sched) throws InvalidGrammarException {

    String res = "";
    for (AGEval.Class c : ast.classes) res += classHeader(c, ast.extendedClasses, sched);
    for (AGEval.IFace i : ast.interfaces) res += interfaceHeader(i, ast.extendedClasses);

    String union = "union ExtraAny {\n";
    for (AGEval.Class c : ast.classes)
      union += "  ExtraSub" + c.getName() + " Sub" + c.getName() + ";\n";     
    for (AGEval.IFace i : ast.interfaces)
      union += "  ExtraSub" + i.getName() + " Sub" + i.getName() + ";\n";

    union += "};\n";

    /*
    String tags = "enum aletags { ";
    boolean isFirst = true;
    for (AGEval.Class c : aleg.classes) {
      if (isFirst) isFirst = false;
      else tags += ", ";
      tags += "TOK_" + c.getName().toUpperCase();
    }
    tags += " };\n";   
    String getters = getFieldsByTag(aleg);
     */

    String visitHeaders = "";
    for (int i = 0; i < numVisits; i++)
      visitHeaders += "bool visit_" + i + "(bool isGlobalCall, VISITPARAMS);\n";

    String body = res + union + /*tags + getters + */ visitHeaders;
    String pre =
        "#ifndef VISITORS_H\n" +
            "#define VISITORS_H\n" +
            "#include \"constants.h\"\n" +
            "#ifdef EXTRA_DATA\n\n\n" +
            "struct SNode;\n" +
            "#include \"sssmacros.h\"\n" +
            //"#include \"extradatahandler.h\"\n" +
            "\n";
    String post = "\n#endif //EXTRA_DATA\n\n#endif //VISITORS_H\n";

    return (pre + body + post);
  }

  public static String printCurrentPipelineBatch (Schedule schedule2) throws InvalidGrammarException {
    String res = "#ifdef DEBUGY\n  tbb::tick_count::interval_t interval;\n";
    //int step = 0;
    for (int step = 0; step <= schedule2.binding.get("P").toTermArray().length; step++) {
      res += "tbb::tick_count t" + step + ";\n";     
    }
    //res += "\ntbb::tick_count t" + step + ";\n"; //last
    res += "t0 = tbb::tick_count::now();\n#endif //DEBUGY\n\n";

    int pass = 0;
    int lockC = 0
    for (Term visit : schedule2.binding.get("P").toTermArray()) {
      String traversal = (lockC + 1) % 2 == 0 ? "false" : "true";

      res +=
          "#if defined(DEBUGY) && defined(BLOCKPARALLELTREE)\n" +
              "  cout << \"batch " + pass + ": \" << endl;\n" +
              "  resetOrdering(browser->rstree.second.second.second);\n" +
              "#endif //DEBUGY\n";

      String stencil = visit.arg(2).arg(1).toString();
      if (stencil.equals("tdLtrU")) {
        res += "  visit_" + pass + "(true, VISITARGS(*root, *root, NULL));\n";
      } else if (stencil.equals("td")) {
        res +=
            "#if defined(TBBBLOCKPARALLELTREE) || defined(TBBBLOCKPARALLELTREEOPT) || defined(TBBBLOCKPARALLELTREECONT)\n" +
                "  inheritVisitBlock<visit_" + pass + ", " + traversal + ">(root, sb);\n" +
                "#elif defined(TBBGRAPHSOLVER)\n" +
                "  parallelInheritFTL<inheritVisitBlockFlat<visit_" + pass + ", " + traversal + ">, visit_" + pass + ">(root, sb, numBlocks);\n" +
                "#else\n" +
                "  p.batch(v" + pass + ");\n" +
                "#endif\n";     
        lockC++;
      } else if (stencil.equals("bu")) {
        res +=
            "#if defined(TBBBLOCKPARALLELTREE) || defined(TBBBLOCKPARALLELTREEOPT) || defined(TBBBLOCKPARALLELTREECONT)\n" +
                "  synthesizeVisitBlock<visit_" + pass + ", true>(root, sb);\n" +
                "#elif defined(TBBGRAPHSOLVER)\n" +
                "  parallelSynthesizeFTL<synthesizeVisitBlockFlat<visit_" + pass + ", " + traversal + ">, visit_" + pass + ">(root, fringe, numBlocks);\n" +
                "#else\n" +
                "  p.batch(v" + pass + ");\n" +
                "#endif\n";
        lockC++;
      } else if (stencil.equals("buSubInorder")) {
        res +=
            "#if defined(TBBBLOCKPARALLELTREE) || defined(TBBBLOCKPARALLELTREEOPT) || defined(TBBBLOCKPARALLELTREECONT)\n" +
                "  synthesizeVisitBlock<visit_" + pass + ", true>(root, sb);\n" +
                "#elif defined(TBBGRAPHSOLVER)\n" +
                "  parallelSynthesizeFTL<synthesizeVisitBlockFlat<visit_" + pass + ", " + traversal + ">, visit_" + pass + ">(root, fringe, numBlocks);\n" +
                "#else\n" +
                "  p.batch(v" + pass + ");\n" +
                "#endif\n";
        lockC++;
      } else {
        throw new InvalidGrammarException("Unknown stencil type: " + stencil);
      }
      res += "#ifdef DEBUGY\n  cout << \"  (batch done.)\" << endl;\n#endif //DEBUGY\n";
      pass++;
      res +=
          "#ifdef DEBUGY\nt" + pass + " = tbb::tick_count::now();\n#endif //DEBUGY\n";     
    }
    res += "\n";
    res += "#ifdef DEBUGY\ndouble sum = 0;\n";   
    for (int step = 0; step <= schedule2.binding.get("P").toTermArray().length; step++) {
      res +=
          "interval = t" + (step+1) + " - t" + step + ";\n" +
              "printf(\"Visit, " + step + ", %g\\n\", interval.seconds());\n" +
              "sum += interval.seconds();\n";   
    }
    res += "printf(\"Final, %g\\n\", sum);\n#endif //DEBUGY\n";
    return res;
  }

public static String printCurrentPipelineDelayedBatch (Schedule schedule2) throws InvalidGrammarException {
  String res = "#ifdef DEBUGY\ntbb::tick_count::interval_t interval;\n";
  //int step = 0;
  for (int step = 0; step <= schedule2.binding.get("P").toTermArray().length; step++) {
    res += "tbb::tick_count t" + step + ";\n";   
  }
  //res += "\ntbb::tick_count t" + step + ";\n"; //last
  res += "t0 = tbb::tick_count::now();\n#endif //DEBUGY\n\n";
 
  int pass = 0;
  int lockC = 0
  for (Term visit : schedule2.binding.get("P").toTermArray()) {
    String traversal = (lockC + 1) % 2 == 0 ? "false" : "true";

    res +=
      "#if defined(DEBUGY) && defined(BLOCKPARALLELTREE)\n" +
      "  cout << \"batch " + pass + ": \" << endl;\n" +
      "  resetOrdering(browser->rstree.second.second.second);\n" +
      "#endif //DEBUGY\n";
   
    String stencil = visit.arg(2).arg(1).toString();
    if (stencil.equals("tdLtrU")) {
      res += "  visit_" + pass + "(true, VISITARGS(*root, *root, NULL));\n";
    } else if (stencil.equals("td")) {
      res +=
        "#if defined(TBBBLOCKPARALLELTREE) || defined(TBBBLOCKPARALLELTREEOPT) || defined(TBBBLOCKPARALLELTREECONT)\n" +
        "  inheritVisitBlock<visit_" + pass + ", " + traversal + ">(root, sb);\n" +
        "#elif defined(TBBGRAPHSOLVER)\n" +
        "  parallelInheritFTL<inheritVisitBlockFlat<visit_" + pass + ", " + traversal + ">, visit_" + pass + ">(root, sb, numBlocks);\n" +
        "#else\n" +
        "  p.batchP(v" + pass + ");\n" +
        "#endif\n";     
      lockC++;
    } else if (stencil.equals("bu")) {
      res +=
        "#if defined(TBBBLOCKPARALLELTREE) || defined(TBBBLOCKPARALLELTREEOPT) || defined(TBBBLOCKPARALLELTREECONT)\n" +
        "  synthesizeVisitBlock<visit_" + pass + ", true>(root, sb);\n" +
        "#elif defined(TBBGRAPHSOLVER)\n" +
        "  parallelSynthesizeFTL<synthesizeVisitBlockFlat<visit_" + pass + ", " + traversal + ">, visit_" + pass + ">(root, fringe, numBlocks);\n" +
        "#else\n" +
        "  p.batchP(v" + pass + ");\n" +
        "#endif\n";
      lockC++;
    } else if (stencil.equals("buSubInorder")) {
      res +=
          "#if defined(TBBBLOCKPARALLELTREE) || defined(TBBBLOCKPARALLELTREEOPT) || defined(TBBBLOCKPARALLELTREECONT)\n" +
          "  synthesizeVisitBlock<visit_" + pass + ", true>(root, sb);\n" +
          "#elif defined(TBBGRAPHSOLVER)\n" +
          "  parallelSynthesizeFTL<synthesizeVisitBlockFlat<visit_" + pass + ", " + traversal + ">, visit_" + pass + ">(root, fringe, numBlocks);\n" +
          "#else\n" +
          "  p.batchP(v" + pass + ");\n" +
          "#endif\n";
        lockC++;
    } else {
      throw new InvalidGrammarException("Unknown stencil type: " + stencil);
    }
    res += "#ifdef DEBUGY\n  cout << \"  (batch done.)\" << endl;\n#endif //DEBUGY\n";
    pass++;
    res +=
      "#ifdef DEBUGY\nt" + pass + " = tbb::tick_count::now();\n#endif // DEBUGY\n";     
  }
  res += "\n";
  res += "#ifdef DEBUGY\ndouble sum = 0;\n";
 
  for (int step = 0; step < schedule2.binding.get("P").toTermArray().length; step++) {
    res +=
      "interval = t" + (step+1) + " - t" + step + ";\n" +
      "printf(\"Visit, " + step + ", %g\\n\", interval.seconds());\n" +
        "sum += interval.seconds();\n";
    step++;
  }
  res += "printf(\"Final, %g\\n\", sum);\n#endif //DEBUGY\n";
  return res;
}

public String printCurrentPipelineHeaders (Hashtable<Variable, Term> binding) throws InvalidGrammarException {
  String res = "";
  int pass = 0;
  int lockC = 0;
  //FIXME fuse inh/syn
  for (Term visit : binding.get("P").toTermArray()) {
    //System.err.println(visit.toString());
    String stencil = visit.arg(2).arg(1).toString();
    String traversal = (lockC + 1) % 2 == 0 ? "false" : "true";
    if (stencil.equals("tdLtrU")) {
      System.out.println("Pass " + pass + ": inorder");
      //res += "  WSPiplineInorder<visit_" + pass + "> v" + pass + "(root);\n";
      res += "  //no setup for inorder visit " + pass + "\n";
    } else if (stencil.equals("td")) {
      System.out.println("Pass " + pass + ": td");
      res +=
        "#ifdef PTHREADWSBLOCKS\n" +
        "  WSPipelineInherit<visit_" + pass + ", " + traversal + "> *v" + pass + ";\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADBLOCKS)\n" +
        "  WSPipelineInherit<visit_" + pass + ", " + traversal + "> *v" + pass + ";\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADCOARSEBLOCKS)\n" +
        "  WSPipelineInherit<visit_" + pass + ", " + traversal + "> *v" + pass + ";\n" +
        "#elif defined(TBBBLOCKPARALLELTREE) || defined(TBBBLOCKPARALLELTREEOPT) || defined(TBBBLOCKPARALLELTREECONT) || defined(TBBGRAPHSOLVER)\n" +
        "  //no setup\n" +
        "#elif defined(BLOCKPARALLELTREE) || defined(PREALLOCATETREE)\n" +
        "  WSPipelineInherit<visit_" + pass + ", " + traversal + "> *v" + pass + ";\n" +
        "#elif defined(VECTORLAYOUT)\n" +
        "  WSPipelineInherit<visit_" + pass + ", " + traversal + "> *v" + pass + ";\n" +
        "#else\n" +
        "  ??\n" +
        "#endif\n";
      lockC++;
    } else if (stencil.equals("bu")) {
      System.out.println("Pass " + pass + ": bu");
      res +=
        "#ifdef PTHREADWSBLOCKS\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> *v" + pass + ";\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADBLOCKS)\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> *v" + pass + ";\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADCOARSEBLOCKS)\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> *v" + pass + ";\n" +
        "#elif defined(TBBBLOCKPARALLELTREE) || defined(TBBBLOCKPARALLELTREEOPT) || defined(TBBBLOCKPARALLELTREECONT) || defined(TBBGRAPHSOLVER)\n" +
        "  //no setup\n" +
        "#elif defined(BLOCKPARALLELTREE) || defined(PREALLOCATETREE)\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> *v" + pass + ";\n" +
        "#elif defined(VECTORLAYOUT)\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> *v" + pass + ";\n" +
        "#else\n" +
        "  ??\n" +
        "#endif\n";
      lockC++;
    } else if (stencil.equals("buSubInorder")) {
      System.out.println("Pass " + pass + ": buSubInorder");
      res +=
        "#ifdef PTHREADWSBLOCKS\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> *v" + pass + ";\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADBLOCKS)\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> *v" + pass + ";\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADCOARSEBLOCKS)\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> *v" + pass + ";\n" +
        "#elif defined(TBBBLOCKPARALLELTREE) || defined(TBBBLOCKPARALLELTREEOPT) || defined(TBBBLOCKPARALLELTREECONT) || defined(TBBGRAPHSOLVER)\n" +
        "  //no setup\n" +
        "#elif defined(BLOCKPARALLELTREE) || defined(PREALLOCATETREE)\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> *v" + pass + ";\n" +
        "#elif defined(VECTORLAYOUT)\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> *v" + pass + ";\n" +
        "#else\n" +
        "  ??\n" +
        "#endif\n";
      lockC++;
    } else {
      throw new InvalidGrammarException("Unknown stencil type: " + stencil);
    }
    pass++;
   
  }     
  return res;   
}

public String printCurrentPipelineBuild (Hashtable<Variable, Term> binding) throws InvalidGrammarException {
  String res = "";
  int pass = 0;
  int lockC = 0;
  //FIXME fuse inh/syn
  for (Term visit : binding.get("P").toTermArray()) {
    //System.err.println(visit.toString());
    String stencil = visit.arg(2).arg(1).toString();
    String traversal = (lockC + 1) % 2 == 0 ? "false" : "true";
    if (stencil.equals("tdLtrU")) {
      System.out.println("Pass " + pass + ": inorder");
      //res += "  WSPiplineInorder<visit_" + pass + "> v" + pass + "(root);\n";
      res += "  //no setup for inorder visit " + pass + "\n";
    } else if (stencil.equals("td")) {
      System.out.println("Pass " + pass + ": td");
      res +=
        "#ifdef PTHREADWSBLOCKS\n" +
        "  WSPipelineInherit<visit_" + pass + ", " + traversal + "> v" + pass + "(root, sb, steals);\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADBLOCKS)\n" +
        "  WSPipelineInherit<visit_" + pass + ", " + traversal + "> v" + pass + "(root, sb);\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADCOARSEBLOCKS)\n" +
        "  WSPipelineInherit<visit_" + pass + ", " + traversal + "> v" + pass + "(root, sched, numThreads);\n" +
        "#elif defined(TBBBLOCKPARALLELTREE) || defined(TBBBLOCKPARALLELTREEOPT) || defined(TBBBLOCKPARALLELTREECONT) || defined(TBBGRAPHSOLVER)\n" +
        "  //no setup\n" +
        "#elif defined(BLOCKPARALLELTREE) || defined(PREALLOCATETREE)\n" +
        "  WSPipelineInherit<visit_" + pass + ", " + traversal + "> v" + pass + "(root, treeSize);\n" +
        "#elif defined(VECTORLAYOUT)\n" +
        "  WSPipelineInherit<visit_" + pass + ", " + traversal + "> v" + pass + "(root, q);\n" +
        "#else\n" +
        "  ??\n" +
        "#endif\n";
      lockC++;
    } else if (stencil.equals("bu")) {
      System.out.println("Pass " + pass + ": bu");
      res +=
        "#ifdef PTHREADWSBLOCKS\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> v" + pass + "(root, sb, steals);\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADBLOCKS)\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> v" + pass + "(root, sb);\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADCOARSEBLOCKS)\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> v" + pass + "(root, sched, numThreads);\n" +
        "#elif defined(TBBBLOCKPARALLELTREE) || defined(TBBBLOCKPARALLELTREEOPT) || defined(TBBBLOCKPARALLELTREECONT) || defined(TBBGRAPHSOLVER)\n" +
        "  //no setup\n" +
        "#elif defined(BLOCKPARALLELTREE) || defined(PREALLOCATETREE)\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> v" + pass + "(root, treeSize);\n" +
        "#elif defined(VECTORLAYOUT)\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> v" + pass + "(root, q);\n" +
        "#else\n" +
        "  ??\n" +
        "#endif\n";
      lockC++;
    } else if (stencil.equals("buSubInorder")) {
      System.out.println("Pass " + pass + ": buSubInorder");
      res +=
        "#ifdef PTHREADWSBLOCKS\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> v" + pass + "(root, sb, steals);\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADBLOCKS)\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> v" + pass + "(root, sb);\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADCOARSEBLOCKS)\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> v" + pass + "(root, sched, numThreads);\n" +
        "#elif defined(TBBBLOCKPARALLELTREE) || defined(TBBBLOCKPARALLELTREEOPT) || defined(TBBBLOCKPARALLELTREECONT) || defined(TBBGRAPHSOLVER)\n" +
        "  //no setup\n" +
        "#elif defined(BLOCKPARALLELTREE) || defined(PREALLOCATETREE)\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> v" + pass + "(root, treeSize);\n" +
        "#elif defined(VECTORLAYOUT)\n" +
        "  WSPipelineSynthesize<visit_" + pass + ", " + traversal + "> v" + pass + "(root, q);\n" +
        "#else\n" +
        "  ??\n" +
        "#endif\n";
      lockC++;
    } else {
      throw new InvalidGrammarException("Unknown stencil type: " + stencil);
    }
    pass++;   
   
  }     
  return res;
}

public String printCurrentPipelineDelayedBuild (Hashtable<Variable, Term> binding) throws InvalidGrammarException {
  String res = "";
  int pass = 0;
  int lockC = 0;
  //FIXME fuse inh/syn
  for (Term visit : binding.get("P").toTermArray()) {
    //System.err.println(visit.toString());
    String stencil = visit.arg(2).arg(1).toString();
    String traversal = (lockC + 1) % 2 == 0 ? "false" : "true";
    if (stencil.equals("tdLtrU")) {
      System.out.println("Pass " + pass + ": inorder");
      //res += "  WSPiplineInorder<visit_" + pass + "> v" + pass + "(root);\n";
      res += "  //no setup for inorder visit " + pass + "\n";
    } else if (stencil.equals("td")) {
      System.out.println("Pass " + pass + ": td");
      res +=
        "#ifdef PTHREADWSBLOCKS\n" +
        "  v" + pass + " = new WSPipelineInherit<visit_" + pass + ", " + traversal + ">(root, sb, steals);\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADBLOCKS)\n" +
        "  v" + pass + " = new WSPipelineInherit<visit_" + pass + ", " + traversal + ">(root, sb);\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADCOARSEBLOCKS)\n" +
        "  v" + pass + " = new WSPipelineInherit<visit_" + pass + ", " + traversal + ">(root, sched, numThreads);\n" +
        "#elif defined(TBBBLOCKPARALLELTREE) || defined(TBBBLOCKPARALLELTREEOPT) || defined(TBBBLOCKPARALLELTREECONT) || defined(TBBGRAPHSOLVER)\n" +
        "  //no setup\n" +
        "#elif defined(BLOCKPARALLELTREE) || defined(PREALLOCATETREE)\n" +
        "  v" + pass + " = new WSPipelineInherit<visit_" + pass + ", " + traversal + ">(root, treeSize);\n" +
        "#elif defined(VECTORLAYOUT)\n" +
        "  v" + pass + " = new WSPipelineInherit<visit_" + pass + ", " + traversal + ">(root, q);\n" +
        "#else\n" +
        "  ??\n" +
        "#endif\n";
      lockC++;
    } else if (stencil.equals("bu")) {
      System.out.println("Pass " + pass + ": bu");
      res +=
        "#ifdef PTHREADWSBLOCKS\n" +
        "  v" + pass + " = new WSPipelineSynthesize<visit_" + pass + ", " + traversal + ">(root, sb, steals);\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADBLOCKS)\n" +
        "  v" + pass + " = new WSPipelineSynthesize<visit_" + pass + ", " + traversal + ">(root, sb);\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADCOARSEBLOCKS)\n" +
        "  v" + pass + " = new WSPipelineSynthesize<visit_" + pass + ", " + traversal + ">(root, sched, numThreads);\n" +
        "#elif defined(TBBBLOCKPARALLELTREE) || defined(TBBBLOCKPARALLELTREEOPT) || defined(TBBBLOCKPARALLELTREECONT) || defined(TBBGRAPHSOLVER)\n" +
        "  //no setup\n" +
        "#elif defined(BLOCKPARALLELTREE) || defined(PREALLOCATETREE)\n" +
        "  v" + pass + " = new WSPipelineSynthesize<visit_" + pass + ", " + traversal + ">(root, treeSize);\n" +
        "#elif defined(VECTORLAYOUT)\n" +
        "  v" + pass + " = new WSPipelineSynthesize<visit_" + pass + ", " + traversal + ">(root, q);\n" +
        "#else\n" +
        "  ??\n" +
        "#endif\n";
      lockC++;
    } else if (stencil.equals("buSubInorder")) {
      System.out.println("Pass " + pass + ": buSubInorder");
      res +=
        "#ifdef PTHREADWSBLOCKS\n" +
        "  v" + pass + " = new WSPipelineSynthesize<visit_" + pass + ", " + traversal + ">(root, sb, steals);\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADBLOCKS)\n" +
        "  v" + pass + " = new WSPipelineSynthesize<visit_" + pass + ", " + traversal + ">(root, sb);\n" +
        "#elif defined(BLOCKPARALLELTREE) && defined(PTHREADCOARSEBLOCKS)\n" +
        "  v" + pass + " = new WSPipelineSynthesize<visit_" + pass + ", " + traversal + ">(root, sched, numThreads);\n" +
        "#elif defined(TBBBLOCKPARALLELTREE) || defined(TBBBLOCKPARALLELTREEOPT) || defined(TBBBLOCKPARALLELTREECONT) || defined(TBBGRAPHSOLVER)\n" +
        "  //no setup\n" +
        "#elif defined(BLOCKPARALLELTREE) || defined(PREALLOCATETREE)\n" +
        "  v" + pass + " = new WSPipelineSynthesize<visit_" + pass + ", " + traversal + ">(root, treeSize);\n" +
        "#elif defined(VECTORLAYOUT)\n" +
        "  v" + pass + " = new WSPipelineSynthesize<visit_" + pass + ", " + traversal + ">(root, q);\n" +
        "#else\n" +
        "  ??\n" +
        "#endif\n";
      lockC++;
    } else {
      throw new InvalidGrammarException("Unknown stencil type: " + stencil);
    }
    pass++;
   
  }     
  return res;
}

///////////////////////////////////////////////////////////////////////////////
// Visitors generator methods
///////////////////////////////////////////////////////////////////////////////

 
public void generateParseFiles(ALEParser ast, Schedule sched, String browserPath, boolean verbose, String functionHeadersRaw) throws InvalidGrammarException {
  //grammar.generateFiles(outputDir, verbose);
  //CSS parser
 
    final String fileName = "extradatahandler";
    final String exprName = "aleactions";
   
    String functionHeaders =
      "#include \"ftlstdlib.h\"\n" +
      "#include \"" + fileName + ".h\"\n" + functionHeadersRaw;
     
    try {
      FileWriter headerWriter = new FileWriter(new File(browserPath + File.separator + fileName +".h"));
      headerWriter.write(CppParserGenerator.header(ast));
      headerWriter.close();
      if (verbose) {
        System.out.println("=== PARSER HEADER ===\n" + CppParserGenerator.header(ast));
      }
    } catch (IOException e) {
      System.out.println("Failure to generate parser header: " + e.toString());
      System.exit(1);
    }

    try {
      FileWriter cppWriter = new FileWriter(new File (browserPath + File.separator + fileName + ".cpp"));
      cppWriter.write(CppParserGenerator.body(ast));
      cppWriter.close();
      if (verbose) {
        System.out.println("=== PARSER BODY ===\n" + CppParserGenerator.body(ast));
      }
    } catch (IOException e) {
      System.out.println("Failure to generate parser body: " + e.toString());
      System.exit(1);
    }
   
    try {
      FileWriter propWriter = new FileWriter(new File (browserPath + File.separator + fileName + ".properties"));
      propWriter.write(CppParserGenerator.properties(ast.classes, ast.interfaces));
      propWriter.close();
      if (verbose) {
        System.out.println("=== PROPERTIES ===\n" + CppParserGenerator.properties(ast.classes, ast.interfaces));
      }
    } catch (IOException e) {
      System.out.println("Failure to generate parser properties file: " + e.toString());
      System.exit(1);         
    }

   
    System.out.println("Generated parser extensions at " + browserPath + File.separator  + fileName + ".(h, cpp, properties)");
//ALEG
   
    try {
      FileWriter exprWriter = new FileWriter(new File (browserPath + File.separator + exprName + ".h"));
      exprWriter.write(functionHeaders);
      exprWriter.close();
      if (verbose) {
        System.out.println("=== FUNCS ===\n" + functionHeaders);
      }
    } catch (IOException e) {
      System.out.println("Failure to generate expression (semantic actions) file: " + e.toString());
      System.exit(1);         
    }
   
    System.out.println("Generated expression semantic actions at " + browserPath + File.separator + exprName + ".h");
}

public String preVisits (AGEvaluator aleg, Schedule sched) {
  String visitPre =
    "#include \"constants.h\"\n" +
    "#ifdef EXTRA_DATA\n\n" +
        "#include \"predefinedactions.h\"\n" +     
    "#include \"visitors.h\"\n" +
    "#include \"extradatahandler.h\"\n" +
    "#include \"aleactions.h\"\n" +
    "#include \"sss.h\"\n" +
    "#include \"sssmacros.h\"\n\n";
 
  String visitHelpers = "";
  for (AGEval.Class c : aleg.classes)
    visitHelpers += CppGenerator.assignAliases(c, sched._ast);

 
  visitHelpers +=
    "bool isInorder(SNode *node, int pass) {\n" +
    "  switch (pass) {\n";
  for (int i = 0; i < sched.buSubInorderBuIn.size(); i++) {
    visitHelpers  += "    case " + i + ":\n";
    HashSet<AGEval.Class>bus = sched.buSubInorderBus.get(i);
    if (bus == null) {
      visitHelpers += "#ifdef DEBUGY\n  cout << \" Did not expect inorder call for pass " + i + " \" << endl;\n#endif //DEBUGY\n"
    } else {
      HashSet<AGEval.Class> ios = new HashSet<AGEval.Class>(aleg.classes);
      ios.removeAll(bus);
      visitHelpers  += "      switch (node->data.parseData.display) {\n";       
      for (AGEval.Class cls : ios)
        visitHelpers  += "        case ExtraDataHandler::TOK_" + cls.getName().toUpperCase() +": return true; \n";       
      visitHelpers  += "        default: return false;\n";
      visitHelpers  += "      }\n";
    }
  }
  visitHelpers  += "    default: \n";
  visitHelpers += "#ifdef DEBUGY\n    cout << \" Unknown pass \" << pass << endl;\n#endif //DEBUGY\n"
  visitHelpers += "    return false;\n";
  visitHelpers  += "  }\n";
  visitHelpers  += "}\n";

 
  return visitPre + visitHelpers;
}

public String postVisits (AGEvaluator aleg, Schedule sched) {
  return visitDispatchers(sched.numVisits(), aleg, sched.buSubInorderBuIn, sched.buSubInorderBus) + "\n#endif //EXTRA_DATA\n"
}

public static String visitorFile ="visitors";
//final String dataFile = "unions";
public static String pipelineFile = "sequence";


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


@Override
public String rhsToVal(String lhs, Class cls, ALEParser ast) throws InvalidGrammarException
  boolean isParent;
  boolean isParseData;
  String child;
  String prop;
  if (lhs.split("@").length == 2) {
    child = lhs.split("@")[0];
    isParent = child.equals("self");
    prop = lhs.split("@")[1];       
//    if (prop.contains("$") && child.equals("self")) {
//      System.err.println("CppGen: Cannot use intra-reduction accessors (self$$, ...), caught on use " + child + " in " + lhs);
//      //throw new InvalidGrammarException("Cannot use intra-reduction accessors (self$$, ...), caught on use " + child + " in " + lhs);
//    }
  } else {
      if (ast.types.get("displayType").contains(lhs.toLowerCase())) return "ExtraDataHandler::TOK_" + lhs.toUpperCase();     
    child = "self";
    isParent = true;
    prop = lhs;
  }
 
  String cleanProp = prop.replace("$-", "").replace("$$", "").replace("$i", "").toLowerCase();
 
  try {
    //String checkProp = prop.replace("$i", "");
    ExtendedVertex v = Generator.extendedGet(ast, cls, lhs.replace("$-", "").replace("$$", "").replace("$i", ""));
      isParseData = v.isInput;
    } catch (InvalidGrammarException e) {
      isParseData = false;
//      String checkProp = prop.replace("$i", "");   
//      System.err.println("failed rhs parse data on " + lhs + " (checkProp: " + checkProp + ")");
    } catch (NullPointerException e) {
      System.err.println("rhsToVal null pointer on " + cls.getName() + "::" + lhs);
      e.printStackTrace();
      throw e;
    }

    if (prop.contains("$$")) {
      if (isParent) {
        return "computeData.classData.Sub" + cls.getName() + "." + cleanProp;           
      } else if (Generator.childrenContains(ast.extendedClasses.get(cls).multiChildren.keySet(), child)) {
        return "computeData.classData.Sub" + cls.getName() + "." + child.toLowerCase() + "_" + cleanProp + "_last";           
      } else {
        throw new InvalidGrammarException("Cannot access $$ attrib of a non-multi child / self reduction: " + lhs)
      }
    } else if (prop.contains("$i")) {
      //throw new InvalidGrammarException("$i not handled in C++ backend yet");
      //System.err.println("$i not handled in C++ backend yet");
      if (isParent) {
        throw new InvalidGrammarException("Cannot access $i of self attrib: " + lhs);
        //return "computeData.classData.Sub" + cls.getName() + "." + cleanProp;    
      } else if (Generator.childrenContains(ast.extendedClasses.get(cls).multiChildren.keySet(), child)) {
        if (isParseData) {         
          if (cleanProp.equals("display")) return "loopChild->data.parseData.display";
          else return "loopChild->data.parseData.genData.extraParse" + cls.getChildByName(child).getName() + ".fld_" + cleanProp;
        }
        else return "loopChild->data.computeData.classData.Sub" + cls.getChildByName(child) + "." + cleanProp;       
      } else {
        throw new InvalidGrammarException("Cannot access $i attrib of a non-multi child: " + lhs);
        //return "parseFloat(getChildByRefName(node,\"" + child + "\").getAttribute(\"" + cleanProp + "\"))"; 
      }         
    } else if (prop.contains("$-")) {
      if (isParent) {
        //by definition, cannot be parse data (for now..)
        //FIXME check sink is scheduled in same loop
        return "computeData.classData.Sub" + cls.getName() + "." + cleanProp;
      } else if (Generator.childrenContains(ast.extendedClasses.get(cls).multiChildren.keySet(), child)) {
        String init = "computeData.classData.Sub" + cls.getName() + "." + child.toLowerCase() + "_" + cleanProp + "_init";
        String step = "(PREV())->data.computeData.classData.Sub" + cls.getChildByName(child) + "." + cleanProp;
        return "(STEP() == 1 ? (" + init + ") : (" + step + "))";
        //return "(PREV())->data.computeData.classData.Sub" + cls.getChildByName(child) + "." + cleanProp;
        //return " parseFloat((i == 0 ? node.getAttribute(\"" + child.toLowerCase() + "_" + cleanProp + "_init\")" + " : children[i-1].getAttribute(\"" + cleanProp + "\")))";
      } else {
        throw new InvalidGrammarException("Cannot access $- attrib of a non-multi child: " + lhs);
        //by definition, cannot be parse data (for now..)
//        System.err.println("check cpp prev child iter name"); //FIXME
//        String init = "computeData.classData.Sub" + cls.getName() + "." + cleanProp + "_init";
//        String cur = "(loopChild - 1)->data.computeData.classData.Sub" + cls.getChildByName(child) + "." + cleanProp;
//        return "(i == 0 ? " + init + " : " + cur + ")";
      }
    } else {
      if (isParent) {
        if (isParseData && cleanProp.equals("display")) return "parseData.display";
        else if (isParseData) return "parseData.genData.extraParse" + cls.getName() + "." + (isParseData ? "fld_" : "") + cleanProp;
        else return  "computeData.classData.Sub" + cls.getName() + "." + (isParseData ? "fld_" : "") + cleanProp;
       
      } else if (ast.extendedClasses.get(cls).multiChildren.containsKey(child)) {
//        throw new InvalidGrammarException("Cannot read multichild attrib without indexer ($-, ...): " + lhs);
        //FIXME currently allowed because logging might read back on "loop ... { ... child.x := ... }"
        if (isParseData && cleanProp.equals("display")) return "loopChild->data.parseData.display";
        if (isParseData) return "loopChild->data.parseData.genData.extraParse" + cls.getChildByName(child).getName() + ".fld_" + cleanProp;
        else return "loopChild->data.computeData.classData.Sub" + cls.getChildByName(child) + "." + cleanProp;       
    } else {
      String base =
        "\n#if defined(VERYSMALLTREEPOINTERS)\n" +
          "(&s + s.distanceToLeftmostChild + computeData.classData.Sub" + cls.getName() + ".child_" + child + ")\n" +
          "#elif defined(SMALLTREEPOINTERS)\n" +
          "(s.leftmostChild + computeData.classData.Sub" + cls.getName() + ".child_" + child + ")\n" +
          "#else\n" +
          "(computeData.classData.Sub" + cls.getName() + ".child_" + child + ")\n" +
          "#endif // ptrs\n";
     
        if (isParseData && cleanProp.equals("display")) return base + "->data.parseData.display";
        else if (isParseData) return base + "->data.parseData.genData.extraParse" + cls.getChildByName(child).getName() + ".fld_" + cleanProp;
      else return base + "->data.computeData.classData.Sub" + cls.getChildByName(child) + "." + cleanProp;
      }
    }


}

public String logStmt(int indentSrc, int indentOut, String msg, String rhs) {
  String res = "#ifdef DEBUGY\n";
  for (int i = 0; i < indentSrc; i++) res += " ";
  String space = "";
  for (int i = 0; i < indentOut; i++) space += " ";
  res += "cout << \"" + space +  msg + ": \" << " + rhs + " << endl;\n";
  return res + "#endif //DEBUGY\n";
}
public String logStmtVar(int indentSrc, int indentOut, String msg, ALEParser ast, AGEval.Class cls, String rhs, String rhsAddress) throws InvalidGrammarException {
  ExtendedVertex v = Generator.lookupAttributeExtended(rhs, cls, ast);
  if (v == null) throw new InvalidGrammarException("logStmtVar cpp: could not find " + cls.getName() + "::" + rhs);
  boolean isMaybe = v.isMaybeType;
  boolean isString = v.strType.equals("string");

  String indent = "";
  for (int i = 0; i < indentSrc; i++) indent += " ";
  String space = "";
  for (int i = 0; i < indentOut; i++) space += " ";

  String res = "#ifdef DEBUGY\n";
  if (!isMaybe && isString) {
     res +=
       indent + "if (" + rhsAddress + " == NULL) {\n" +
       indent + "  cout << \"" + space + msg + ": NULL\" << endl;\n" +
       indent + "} else {\n" +
       indent + "  cout << \"" + space +  msg + ": \" << " + rhsAddress + " << endl;\n" +
       indent + "}\n";        
  } else res += "cout << \"" + space +  msg + ": \" << " + rhsAddress + " << endl;\n";
  return res + "#endif //DEBUGY\n";
}

public String functionHeader (ALEParser.Assignment assign, ALEParser ast) throws InvalidGrammarException {
  String fName = assign._class.getName().toLowerCase() + "_" + assign._sink.replace('.','_').replace('@','_');
  String params = "(";
 
  boolean isFirst = true;
  for (String arg : assign._variables.keySet()) {
    if (!isFirst) {
      params += ", ";
    }
    else isFirst = false;
    String rawT = typeStringToCppType(Generator.extendedGet(ast, assign._class, arg).strType);
    ALEParser.ExtendedVertex ev = Generator.lookupAttributeExtended(arg, assign._class, ast);   
    params += (ev != null && ev.isMaybeType ? ("maybeT<" + rawT + ">") : rawT) + " " + assign._variables.get(arg);       
  }
 
  params += ")";
 
  return "static " + typeStringToCppType(Generator.extendedGet(ast, assign._class, assign._sink).strType) +
    " " + fName + " " + params + " { return " + assign._indexedBody + "; }\n";
}

public String openChildLoop(AGEval.Class parent_class, String loopVar, ALEParser ast) {
  return "  SFORLOOPALIAS(loopChild, s, ExtraDataHandler::TOK_" + loopVar.toUpperCase() + ", step) {\n";   
}


public String closeChildLoop() {
  return "  } SFORLOOPALIASEND();";
}

public String openLastChild(AGEval.Class cls, String loopVar) {
  return "    if (step == s.data.computeData.classData.Sub" + cls.getName() + ".child_" + loopVar.toLowerCase() + "_count) {\n";
}

public String closeLastChild() {
  return
      "      break;\n" +
    "    }\n";
}

public String childrenRecur  (Class cls, String childName, int visitNum, ALEParser ast) { 
  return
    //"  SFORLOOP(child, s) {\n" +
    //"    visit_" + visitNum + "(VISITARGS(*child, root, &s)); //recur\n" +
    //"  } SFORLOOPEND(child, s);\n";
    "    visit_" + visitNum + "(false, VISITARGS(*loopChild, root, &s)); //recur\n";
}

public String childRecur(AGEval.Class cls, String childName, int visitNum) {
 
  String childLoc =
    "{\n\n#if defined(VERYSMALLTREEPOINTERS)\n" +
      "SNode *child" + visitNum + " = (&s + s.distanceToLeftmostChild + computeData.classData.Sub" + cls.getName() + ".child_" + childName + ");\n" +
      "#elif defined(SMALLTREEPOINTERS)\n" +
      "SNode *child" + visitNum + " = (s.leftmostChild + computeData.classData.Sub" + cls.getName() + ".child_" + childName + ");\n" +
      "#else\n" +
      "SNode *child" + visitNum + " = (computeData.classData.Sub" + cls.getName() + ".child_" + childName + ");\n" +
      "#endif // ptrs\n";
  return childLoc + "visit_" + visitNum + "(false, VISITARGS(*child" + visitNum + ", root, &s)); //recur\n}\n";
  //String childLoc = "*(&s + s.distanceToLeftmostChild + computeData.classData.Sub" + cls.getName() + ".child_" + childName + ")";
  //return "visit_" + visitNum + "(VISITARGS(" + childLoc + ", root, &s)); //recur\n";         
}

public String visitHeader(Class cls, int visitNum, ALEParser ast) throws InvalidGrammarException {
  String res = "";
 
  String preamble =
    "  EXTRA_DATA_PARSE &parseData = s.data.parseData; \n" +
    "  EXTRA_DATA_COMPUTE &computeData = s.data.computeData;\n" +
    "  \n";
 
  String classPreamble = "#ifdef DEBUGY\n  cout << \"  "  + visitNum + " visit (" + cls.getName() + ")\" << endl;\n#endif //DEBUGY\n";
  //String classPreamble = "#ifdef DEBUGY\n  cout << \"  visit " + cls.getName() + " id: \" << s.data.parseData.id << endl;\n#endif DEBUGY //DEBUGGY\n";
  res += "bool visit_" + cls.getName().toLowerCase() + "_" + visitNum + "(VISITPARAMS) {\n" + classPreamble + preamble;

  if (visitNum == 0) {
    //set aliases and initialize nullaries
      String assignAliases = "  assignAliases_" + cls.getName() + "(VISITARGS(s, root, SPARENT));\n";
      res += assignAliases;
      /*
      for (Function f : cls.getFunctions()) {
        if (f.getSources().length == 0) {
          String call = "  ";// + cls.getName().toLowerCase();
          String lhs = lhsToAddress(f.myDest, cls, ast);
          call += lhs + " = " + f.getName() + "();\n";
          res += call;
        }
      }
      */
  }   
 
  return res;
}

public String visitFooter(Class cls, int visitNum, ALEParser ast) throws InvalidGrammarException {
String res = "#ifdef DEBUGY\n  cout << \"    (leaving "  + visitNum + " visit " + cls.getName() + ")\" << endl;\n#endif //DEBUGY\n";
res += "  return true;\n}\n";
return res;
}


public static void synthesizeCpp(String alePath, String outputDir, String resourceDir, boolean verbose, boolean isFixedChildOrder, boolean useFirstParallel, boolean isExhaustive, int maxLen, GeneratorI generator) throws Exception {
  System.err.println("Setup for CPP build: ");
  System.err.println("  Grammar: " + alePath);
  System.err.println("  Return first found: " + useFirstParallel);
  System.err.println("  Fixed child orders (lexical): " + isFixedChildOrder);
  System.err.println("  Include non-greedy schedules: " + isExhaustive);
  System.err.println("  Max number of visits: " + maxLen);
  System.err.println("  Algorithm: " + resourceDir);
  System.err.println("  Output dest: " + outputDir);
  System.err.println("  Chain loops: " + AGEvaluatorSwipl.chainLoops);
  if (useFirstParallel)
    generator.synthesize(alePath, outputDir, resourceDir, verbose, isFixedChildOrder, isExhaustive, maxLen, false);
  else
    generator.synthesizeAll(alePath, outputDir, resourceDir, verbose, isFixedChildOrder, isExhaustive, maxLen, false);
}


public static void main(String[] args) throws Exception {
  if (args.length == 7) {
    synthesizeCpp(args[1], args[2], args[0], false, new Boolean(args[3]).booleanValue(), new Boolean(args[4]).booleanValue(), new Boolean(args[5]).booleanValue(), new Integer(args[6]).intValue(),
        AGEvaluatorSwipl.chainLoops ? new AbstractGenerator(new CppGenerator()) : new Generator(new CppGenerator()));
  } else
    System.err.println("Arg 0: resource dir (where to fine algorithm.pl");
    System.err.println("Arg 1: grammar path");
    System.err.println("Arg 2: output path");
    System.err.println("Arg 3: allow all child orderings?");
    System.err.println("Arg 4: use first parallel (vs. /variants subdirs)");
    System.err.println("Arg 5: exhaustive or greedy (first prefix)?");
    System.err.println("Arg 6: max length of traversal sequence");
    throw new Exception("Wrong number of arguments");
  }


}

public String output(String baseName, String visitOut, String visitDispatches, String outputDir, boolean write,
    boolean verbose, ALEParser ast, Schedule sched, String fHeaders, Hashtable<Variable, Term> binding, AGEvaluator aleg)
    throws IOException, InvalidGrammarException {

  if (write) {
    AGEvaluatorSwipl.writeFile(outputDir + File.separator + visitorFile + ".cpp", visitOut);
    AGEvaluatorSwipl.writeFile(outputDir + File.separator + visitorFile + ".h", CppGenerator.classesHeader(ast, sched.numVisits(), sched));
   
    //construct and call immediately
    AGEvaluatorSwipl.writeFile(outputDir + File.separator + pipelineFile + ".cpp.construct", printCurrentPipelineBuild(sched.binding));
    AGEvaluatorSwipl.writeFile(outputDir + File.separator + pipelineFile + ".cpp.call", printCurrentPipelineBatch(sched));

    //delayed
    AGEvaluatorSwipl.writeFile(outputDir + File.separator + pipelineFile + ".cpp.headers", printCurrentPipelineHeaders(sched.binding));
    AGEvaluatorSwipl.writeFile(outputDir + File.separator + pipelineFile + ".cpp.delayedConstruct", printCurrentPipelineDelayedBuild(sched.binding));
    AGEvaluatorSwipl.writeFile(outputDir + File.separator + pipelineFile + ".cpp.delayedCall", printCurrentPipelineDelayedBatch(sched));
   
  }
  if (verbose) {
    //System.out.println("=== PIPELINE: === \n" + schedule2.printCurrentPipelineBuild());
    System.out.println("=== HELPERS: === \n" + CppGenerator.classesHeader(ast, sched.numVisits(), sched));
    System.out.println("=== VISITS ===: \n" + visitOut);     
  }
  return "(no CPP out)"; //TODO
}

public String asgnE(String lhs, String rhs) { return lhs + " = " + rhs; }
public String asgnS(String lhs, String rhs) { return asgnE(lhs, rhs) + ";\n"; }

}
TOP

Related Classes of AGEvalSwipl.CppGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.