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 }