001    package escjava.tc;
002    
003    import java.util.Iterator;
004    import java.util.List;
005    import java.util.LinkedList;
006    import java.util.HashMap;
007    import java.util.Map;
008    import javafe.ast.FieldDecl;
009    import javafe.ast.TypeDecl;
010    import javafe.ast.FieldAccess;
011    import javafe.ast.ASTDecoration;
012    import javafe.ast.Expr;
013    import javafe.ast.TypeNameVec;
014    import javafe.ast.TypeName;
015    
016    public class Datagroups {
017    
018        /* Each TypeDecl has a decoration associated with it that contains a
019           Map; this map has key type FieldDecl and value type List.  The
020           FieldDecl is the model variable that has a datagroup and the List is
021           the set of Expr instances in the datagroup.
022    
023           The reason that the same fd has different datagroups depending on the
024           TypeDecl is that the members of a datagroup are those fields mapped into
025           it in a TypeDecl and its supertypes, but not those in other branches of
026           the inheritance tree.
027         */
028    
029        //@ non_null
030        static private final ASTDecoration datagroups = 
031                                              new ASTDecoration("datagroups");
032        
033        //@ non_null
034        static final private List empty = new LinkedList();
035        
036        /** Get the items that are in the datagroup for fd */
037        //@ requires fd != null;
038        static public List get(TypeDecl td, FieldDecl fd) {
039            Map map = (Map)datagroups.get(td);
040            if (map == null) map = initMap(td);
041            List list = (List)map.get(fd);
042            if (list == null) list = empty;
043    /*
044            System.out.println("DG GET: " + td.id + " " + fd.id + ":");
045            Iterator i = list.iterator();
046            while (i.hasNext()) System.out.println(">>> " + i.next());
047    */
048            return list;
049        }
050        
051        /** Add Expr fa to the datagroup for declaration fd in the
052            context of type td; the declaration fd may be in a superclass.
053            When we fetch a contents of a datagroup, we only fetch the fields that
054            are in td or its superclasses and super interfaces. */
055        //@ requires fd != null;
056        //@ requires td != null;
057        static public void add(TypeDecl td, FieldDecl fd, Expr fa) {
058            Map map = (Map) datagroups.get(td);
059            if (map == null) map = initMap(td);
060            List list = (List)map.get(fd);
061            if (list == null) {
062                list = new LinkedList();
063                map.put(fd,list);
064            }
065            list.add(fa);
066    //        System.out.println("ADDING TO " + td.id + " " + fd.id + " : " + fa);
067        }
068    
069        static public Map initMap(TypeDecl td) {
070                //System.out.println("INITIALIZING MAP FOR " + td.id);
071                // If the TypeDecl does not yet have a datagroup map, we create
072                // one and initialize it with all the mappings contained in its
073                // super types, since the TypeDecl will see both the datagroup and
074                // the field mapped into the datagroup.  (This ignores access
075                // visibility).  The supertypes have already been typechecked, so
076                // their maps will be complete.
077                Map map = new HashMap();
078                javafe.tc.TypeSig ts = TypeSig.getSig(td).superClass();
079                if (ts != null) {
080                  //System.out.println("ADD FROM " + ts);
081                  addToMap(map, getMap(ts.getTypeDecl()));
082                }
083                TypeNameVec tv = td.superInterfaces;
084                for (int i=0; i<tv.size(); ++i) {
085                    TypeName si = tv.elementAt(i);
086                    TypeDecl itd = TypeSig.getSig(si).getTypeDecl();
087                    //System.out.println("ADD FROM " + itd.id);
088                    addToMap(map, getMap(itd) );
089                }
090                datagroups.set(td,map);
091                return map;
092        }
093    
094        //@ ensures \result != null;
095        static public Map getMap(TypeDecl td) {
096            Map m = (Map)datagroups.get(td);
097            if (m == null) m = initMap(td);
098            return m;
099        }
100    
101        //@ requires map != null;
102        static public void addToMap(Map map, Map m) {
103            Iterator i = m.entrySet().iterator();
104            while (i.hasNext()) {
105                Map.Entry e = (Map.Entry)i.next();
106                List list = (List) map.get( e.getKey() );
107                if (list == null) {
108                    list = new LinkedList();
109                    map.put( e.getKey(), list);
110                }
111                list.addAll( (List) e.getValue() );
112            //System.out.println("ATM: " + ((FieldDecl)e.getKey()).id);
113            //Iterator ii = list.iterator();
114            //while (ii.hasNext()) System.out.println(">>> " + ii.next());
115            }
116        }
117    
118    }