checkpoint
[sbp.git] / src / edu / berkeley / sbp / meta / Production.java
1 package edu.berkeley.sbp.meta;
2 import edu.berkeley.sbp.util.*;
3 import edu.berkeley.sbp.*;
4 import edu.berkeley.sbp.chr.*;
5 import edu.berkeley.sbp.misc.*;
6 import edu.berkeley.sbp.bind.*;
7 import java.util.*;
8 import java.lang.annotation.*;
9 import java.lang.reflect.*;
10 import java.io.*;
11
12 public  class Production {
13     public String tag;
14     public String nonTerminal;
15     public boolean[] drops;
16     public Element[] elements;
17     public int count = 0;
18
19     public String tag() { return tag==null ? nonTerminal : tag; }
20
21     public Production(String tag, Element[] elements, boolean[] drops) { this(tag, tag, elements, drops); }
22     public Production(String tag, String nonTerminal, Element[] elements, boolean[] drops) {
23         this.tag = tag;
24         this.elements = elements;
25         this.drops = drops;
26         this.nonTerminal = nonTerminal;
27         for(int i=0; i<drops.length; i++)
28             if (!drops[i])
29                 count++;
30     }
31
32     public int[] buildSequence(Bindable _bindable) {
33         Annotation[][] annotations = _bindable.getArgAnnotations();
34         Class[]        types       = _bindable.getArgTypes();
35         String[]       names       = _bindable.getArgNames();
36         String name                = _bindable.getSimpleName();
37         int len                    = annotations.length;
38         int ofs                    = 0;
39         bind.arg[] argtags  = new bind.arg[len];
40         for(int i=0; i<names.length; i++)
41             for(Annotation a : annotations[i+ofs])
42                 if (a instanceof bind.arg)
43                     argtags[i+ofs] = (bind.arg)a;
44
45         int argTagged = 0;
46         boolean hasloc = types.length>0 && types[0]==Input.Region.class;
47         for(int i=0; i<argtags.length; i++) {
48             if (i==0 && types[0]==Input.Region.class) continue;
49             if (argtags[i] != null)
50                 argTagged++;
51         }
52         int numNames = names.length;
53         if (hasloc) numNames--;
54
55         // FIXME: can be smarter here
56         if (argTagged==count) {
57             int[] ret = new int[argtags.length];
58             int j = 0;
59             for(int i=0; i<argtags.length; i++) {
60                 if (i==0 && types[0]==Input.Region.class) continue;
61                 if (argtags[i]==null) continue;
62                 if (argtags[i].value().equals(""))
63                     ret[i] = j++;
64                 else {
65                     ret[i] = -1;
66                     for(int k=0; k<names.length; k++)
67                         if (argtags[i].value().equals(names[k])){
68                             ret[i] = k;
69                             break;
70                         }
71                     if (ret[i]==-1) return null;
72                 }
73             }
74             return ret;
75         } else if (numNames==count) {
76             int[] ret = new int[count];
77             for(int i=0; i<count; i++) ret[i] = i+(hasloc?1:0);
78             return ret;
79         } else {
80             return null;
81         }
82     }
83
84     public boolean isCompatible(Object o) { return isCompatible(Bindable.create(o)); }
85     public boolean isCompatible(Bindable _bindable) {
86         bind.as t = _bindable.getAnnotation(bind.as.class);
87         bind b = _bindable.getAnnotation(bind.class);
88         
89         boolean ok = false;
90         if (t != null && (t.value().equals(tag))) ok = true;
91         if (t != null && ((t.value().equals("") && _bindable.getSimpleName().equals(tag)))) ok = true;
92         if (b != null && _bindable.getSimpleName().equals(tag)) ok = true;
93         
94         if (ok) return buildSequence(_bindable)!=null;
95         
96         return false;
97     }
98     
99     public Sequence makeSequence(Object o) { return makeSequence(Bindable.create(o)); }
100     public Sequence makeSequence(final Bindable _bindable) {
101
102         if (_bindable.getArgTypes().length > 0 &&
103             _bindable.getArgTypes()[0] == Input.Region.class) {
104             Functor<Input.Region,Object> func = new Functor<Input.Region,Object>() {
105                 int[] map = buildSequence(_bindable);
106                 public Object invoke(final Input.Region region) { return _bindable.createBinding(map, region); }
107             };
108             return Sequence.regionRewritingSequence(func, elements, drops);
109         }
110
111         if (_bindable.isAnnotationPresent(bind.raw.class))
112             return Sequence.rewritingSequence(new RawBindingFunctor(tag(), _bindable.createBinding()), elements, drops);
113         int[] map = buildSequence(_bindable);
114         return Sequence.rewritingSequence(new BindingFunctor(tag(), _bindable.createBinding()), elements, drops);
115     }
116
117 }