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 }