using System; using System.Reflection; using edu.neu.ccs.demeterf.util; using edu.neu.ccs.demeterf.control; using edu.neu.ccs.demeterf.dispatch; using edu.neu.ccs.demeterf.lib; using edu.neu.ccs.demeterf.parallel; namespace edu.neu.ccs.demeterf{ /** A Helper Class to implement something like SYB queries. */ public abstract class TU : FC{ // Type Unifying combiner (TU) // Default for objects without fields (unless handled earlier) public T combine(object o1){ return combine(); } /** A Bunch of simple object* methods to catch all the rest */ public T combine(object o1, object o2) { return simplify(new object[]{o2}); } public T combine(object o1, object o2, object o3) { return simplify(new object[]{o2,o3}); } public T combine(object o1, object o2, object o3, object o4) { return simplify(new object[]{o2,o3,o4}); } public T combine(object o1, object o2, object o3, object o4, object o5) { return simplify(new object[]{o2,o3,o4,o5}); } public T combine(object o1, object o2, object o3, object o4, object o5, object o6) { return simplify( new object[]{o2,o3,o4,o5,o6}); } //** More if needed... /** The simplify for an array... called from above */ T simplify(object[] o){ return simplify(o, (T)(o[0]), 1); } /** Recursive fold over the array */ T simplify(object[] o, T t, int i){ if(i >= o.Length)return t; return simplify(o, fold(t, (T)o[i]), i+1); } // * * * * Actual Stuff... * * * * // Clients extend TU and implement the methods below. /** Perform one step of the combination */ public abstract T fold(T accum, T one); /** Default apply (must be implemented for safety) */ public abstract T combine(); /** Use this to do a TU Traversal of an Object. It reflects on the given TUCombiner, and sees what you're * interested in (single argument combine methods), making those * classes BuiltIns */ public T traverse(Object o){ return new Traversal(this, control(this, Control.builtins())).traverse(o); } /** Use this to do a TU Traversal of an Object with a given Control * for optimization purposes. Note: The function object is not run on bypassed edges, so * your methods *must* handle these edges correctly. */ public T traverse(Object o, MutableControl c){ return new Traversal(this, control(this, c)).traverse(o); } /** Use this to do a TU Traversal of an Object. * It reflects on the given TU, and sees what you're * interested in (single argument combine methods), making those * classes BuiltIns */ public static T traverse(Object o, TU tuc){ return new Traversal(tuc, control(tuc, Control.builtins())).traverse(o); } /** Use this to do a TU Traversal of an Object with a given Control * for optimization purposes.
* Note: The function object is not run on bypassed edges, so * your methods *must* handle these edges correctly. */ public static T traverse(Object o, TU tuc, MutableControl c){ return new Traversal(tuc, control(tuc, c)).traverse(o); } /** Uses ParTraversal to do combines in parallel */ public static T partraverse(Object o, TU tuc){ return new ParTraversal(tuc, control(tuc, Control.builtins())).traverse(o); } /** Uses ParTraversal to do combines in parallel */ public static T partraverse(Object o, TU tuc, MutableControl c){ return new ParTraversal(tuc, control(tuc, c)).traverse(o); } /** Collect the implied control from the TU's signatures and add it * to the given MutableControl */ private static MutableControl control(TU tuc, MutableControl c){ foreach(DBEntry dbe in MethodDB.createMDB(tuc.GetType(),Traversal.BuilderMethod).getMethods()){ if(dbe.numArgs() == 1 && !dbe.arg(0).Equals(typeof(object))) c.addBuiltIn(dbe.arg(0)); } return c; } } }