checkpoint
[sbp.git] / src / edu / berkeley / sbp / misc / ReflectiveGrammar.java
index ecf186d..5f90b7f 100644 (file)
@@ -8,12 +8,16 @@ import edu.berkeley.sbp.tib.*;
 import edu.berkeley.sbp.chr.*;
 import edu.berkeley.sbp.util.*;
 
-public class ReflectiveGrammar extends MetaGrammar {
-
+public class ReflectiveGrammar /*extends MetaGrammar*/ {
+    /*
     final Class baseClass;
     public ReflectiveGrammar(Class baseClass) { this.baseClass = baseClass; }
 
     public Object convertLabel(String label) { return new ClassMark(label); }
+    public Object repeatTag() { return arrayMark; }
+
+    private static class ArrayMark { }
+    private static final ArrayMark arrayMark = new ArrayMark();
 
     private static class ClassMark {
         public final String clazz;
@@ -33,45 +37,67 @@ public class ReflectiveGrammar extends MetaGrammar {
 
     public Object build(Tree<Object> t) throws Exception { return buildHead(t, null); }
     public Object buildHead(Tree<Object> t, Class c) throws Exception {
-        System.out.println("buildHead " + (c==null?null:c.getName()) + " " + t);
+        //System.out.println("buildHead " + (c==null?null:c.getName()) + " " + t);
         Object h = t.head();
 
-        if (h != null && h instanceof ClassMark) return buildBody(t, Class.forName(baseClass.getName()+"$"+((ClassMark)h).clazz));
+        if (h != null && h instanceof ClassMark) {
+            String clazz = ReflectiveWalker.mangle(((ClassMark)h).clazz);
+            Class c2 = (c!=null && c.getName().endsWith("$"+clazz)) ? c : Reflection.forNameOrNull(baseClass.getName()+"$"+clazz);
+            if (c2!=null) return buildBody(t, c2);
+            for(Method m : baseClass.getMethods()) {
+                if (!m.getName().equals(clazz)) continue;
+                Object[] o = new Object[m.getParameterTypes().length];
+                for(int i=0; i<o.length; i++)
+                    o[i] = i>=t.numChildren() ? null : buildHead(t.child(i), m.getParameterTypes()[i]);
+                return m.invoke(null, o);
+            }
+            throw new RuntimeException("couldn't figure out what to invoke for ClassMark " + clazz);
+        } else if (h==arrayMark && c==null) {
+            c = Object[].class;            
+        }
         if (c.isArray()) {
             Object[] ret = new Object[t.numChildren()];
             for(int i=0; i<ret.length; i++)
                 ret[i] = buildHead(t.child(i), c.getComponentType());
             return Reflection.lub(ret);
         }
-        if (h==null)                return buildBody(t, c);
-        
         if (c==String.class) return stringify(t);
-        if (c==int.class)    return new Integer(stringify(t));
+        if (c==int.class)    { String s = stringify(t); if (s==null||"".equals(s)) return new Integer(0); return new Integer(s); }
+        if (h==null)         return buildBody(t, c);
 
-        if (t.numChildren() > 0) throw new RuntimeException("can't buildHead() on a tree with children when the head is of type " + h.getClass().getName());
+        if (t.numChildren() > 0)
+            throw new RuntimeException("can't buildHead() on a tree with children when the head is of type " +
+                                       h.getClass().getName() + "(c=="+(c==null?"null":c.getName())+")");
         return h;
     }
 
     public Object buildBody(Tree<Object> t, Class c) throws Exception {
-        System.out.println("buildBody " + (c==null?null:c.getName()) + " " + t);
+        //System.out.println("buildBody " + (c==null?null:c.getName()) + " " + t);
         c = resolveClass(t, c);
+        if (c==null) return buildHead(t, null);
         Object o = c.newInstance();
         Field[] f = c.getFields();
         OUTER: for(int i=0; i<t.numChildren(); i++) {
             Object label = t.label(i);
             Field field = null;
-            if (label!=null) try { field = c.getField(label+""); } catch (NoSuchFieldException _) { }
+            if (label!=null) field = Reflection.getField(c, label+"");
             if (field==null && label != null)
                 for(Method m : c.getMethods())
                     if (m.getName().equals(label)) {
                         m.invoke(o, new Object[] { buildHead(t.child(i), m.getParameterTypes()[0]) });
                         continue OUTER;
                     }
-            if (field==null) System.err.println("warning: skipping field " + label + " ("+i+") on class " + c.getName());
+            if (field==null && label==null) {
+                field = Reflection.getField(c, 0);
+            }
+            if (field==null) {
+                System.err.println("warning: skipping field " + label + " ("+i+") on class " + c.getName());
+                System.err.println("   tree: " + t);
+            }
             else {
                 Object tgt = Reflection.rebuild(buildHead(t.child(i), field.getType()), field.getType());
-                if (tgt instanceof Object[]) tgt = Reflection.lub(tgt);
-                System.err.println("setting field " + field.getName() + " on " + c.getName() + " to " + tgt);
+                //if (tgt instanceof Object[]) tgt = Reflection.lub(tgt);
+                //System.err.println("setting field " + field.getName() + " on " + c.getName() + " to " + tgt);
                 try {
                     field.set(o, tgt);
                 } catch (Exception e) {
@@ -84,23 +110,26 @@ public class ReflectiveGrammar extends MetaGrammar {
 
     public Class resolveClass(Tree<Object> t, Class c) throws Exception {
         if (c==null) return null;
-        System.out.println("resolving " + c.getName());
+        if (c==int.class) return c;
+        if (c==String.class) return c;
+        //System.out.println("resolving " + c.getName());
         if (Reflection.isConcrete(c)) return c;
         Class ret = null;
         Class[] subs = (Class[])c.getField("subclasses").get(null);
         OUTER: for(int i=0; i<subs.length; i++) {
-            System.err.println("trying " + subs[i].getName());
+            //System.err.println("trying " + subs[i].getName());
             for(int j=0; j<t.numChildren(); j++)
                 if (Reflection.getField(subs[i], t.label(j)+"")==null) {
-                    System.err.println("skipping due to " + t.label(j));
+                    //System.err.println("skipping due to " + t.label(j));
                     continue OUTER;
                 }
             if (ret != null)
                 throw new RuntimeException("couldn't decide between two classes:\n  " + subs[i].getName() + "\n  " + ret.getName());
             ret = subs[i];
         }
+        if (t.head()==null) return null;
         if (ret==null) throw new RuntimeException("couldn't find a class to match tree: " + t);
         return ret;
     }
-
+    */
 }