9 public class JavaBuilder {
11 HashSet<Descriptor> checkedDesc=new HashSet<Descriptor>();
12 HashMap<ClassDescriptor, Integer> classStatus=new HashMap<ClassDescriptor, Integer>();
13 public final int CDNONE=0;
14 public final int CDINIT=1;
15 public final int CDINSTANTIATED=2;
20 Stack<MethodDescriptor> toprocess=new Stack<MethodDescriptor>();
21 HashSet<MethodDescriptor> discovered=new HashSet<MethodDescriptor>();
23 /* Maps class/interfaces to all instantiated classes that extend or
24 * implement those classes or interfaces */
26 HashMap<ClassDescriptor, Set<ClassDescriptor>> implementationMap=new HashMap<ClassDescriptor, Set<ClassDescriptor>>();
28 /* Maps methods to the methods they call */
30 HashMap<MethodDescriptor, Set<MethodDescriptor>> callMap=new HashMap<MethodDescriptor, Set<MethodDescriptor>>();
33 HashMap<ClassDescriptor, Set<Pair<MethodDescriptor, MethodDescriptor>>> invocationMap=new HashMap<ClassDescriptor, Set<Pair<MethodDescriptor, MethodDescriptor>>>();
36 public JavaBuilder(State state) {
38 bir=new BuildIR(state);
39 tu=new TypeUtil(state, bir);
40 sc=new SemanticCheck(state, tu, false);
41 bf=new BuildFlat(state,tu);
44 public TypeUtil getTypeUtil() {
48 public BuildFlat getBuildFlat() {
53 ClassDescriptor mainClass=sc.getClass(null, state.main, SemanticCheck.INIT);
54 MethodDescriptor mainMethod=tu.getMain();
55 toprocess.push(mainMethod);
59 void checkMethod(MethodDescriptor md) {
61 sc.checkMethodBody(md.getClassDesc(), md);
63 System.out.println( "Error in "+md );
68 void initClassDesc(ClassDescriptor cd) {
69 if (classStatus.get(cd)==null) {
70 classStatus.put(cd, CDINIT);
71 //TODO...LOOK FOR STATIC INITIALIZERS
75 void computeFixPoint() {
76 while(!toprocess.isEmpty()) {
77 MethodDescriptor md=toprocess.pop();
79 initClassDesc(md.getClassDesc());
80 bf.flattenMethod(md.getClassDesc(), md);
81 processFlatMethod(md);
85 void processCall(MethodDescriptor md, FlatCall fcall) {
86 MethodDescriptor callmd=fcall.getMethod();
88 //First handle easy cases...
89 if (callmd.isStatic()||callmd.isConstructor()) {
90 if (!discovered.contains(callmd)) {
91 discovered.add(callmd);
92 toprocess.push(callmd);
94 callMap.get(md).add(callmd);
98 //Otherwise, handle virtual dispatch...
99 ClassDescriptor cn=callmd.getClassDesc();
100 Set<ClassDescriptor> impSet=implementationMap.get(cn);
102 if (!invocationMap.containsKey(cn))
103 invocationMap.put(cn, new HashSet<Pair<MethodDescriptor,MethodDescriptor>>());
104 invocationMap.get(cn).add(new Pair<MethodDescriptor, MethodDescriptor>(md, callmd));
106 for(ClassDescriptor cdactual:impSet) {
108 while(cdactual!=null) {
109 Set possiblematches=cdactual.getMethodTable().getSetFromSameScope(callmd.getSymbol());
111 for(Iterator matchit=possiblematches.iterator(); matchit.hasNext();) {
112 MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
113 if (callmd.matches(matchmd)) {
114 //Found the method that will be called
115 if (!discovered.contains(matchmd)) {
116 discovered.add(matchmd);
117 toprocess.push(matchmd);
119 callMap.get(md).add(matchmd);
125 //Didn't find method...look in super class
126 cdactual=cdactual.getSuperDesc();
131 void processNew(FlatNew fnew) {
132 TypeDescriptor tdnew=fnew.getType();
133 if (!tdnew.isClass())
135 ClassDescriptor cdnew=tdnew.getClassDesc();
136 Stack<ClassDescriptor> tovisit=new Stack<ClassDescriptor>();
139 while(!tovisit.isEmpty()) {
140 ClassDescriptor cdcurr=tovisit.pop();
141 if (!implementationMap.containsKey(cdcurr))
142 implementationMap.put(cdcurr, new HashSet<ClassDescriptor>());
143 if (implementationMap.get(cdcurr).add(cdnew)) {
144 //new implementation...see if it affects implementationmap
145 if (invocationMap.containsKey(cdcurr)) {
146 for(Pair<MethodDescriptor, MethodDescriptor> mdpair:invocationMap.get(cdcurr)) {
147 MethodDescriptor md=mdpair.getFirst();
148 MethodDescriptor callmd=mdpair.getSecond();
149 ClassDescriptor cdactual=cdnew;
152 while(cdactual!=null) {
153 Set possiblematches=cdactual.getMethodTable().getSetFromSameScope(callmd.getSymbol());
154 for(Iterator matchit=possiblematches.iterator(); matchit.hasNext();) {
155 MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
156 if (callmd.matches(matchmd)) {
157 //Found the method that will be called
158 if (!discovered.contains(matchmd)) {
159 discovered.add(matchmd);
160 toprocess.push(matchmd);
162 callMap.get(md).add(matchmd);
167 //Didn't find method...look in super class
168 cdactual=cdactual.getSuperDesc();
173 if (cdcurr.getSuperDesc()!=null)
174 tovisit.push(cdcurr.getSuperDesc());
175 for(Iterator interit=cdcurr.getSuperInterfaces();interit.hasNext();) {
176 ClassDescriptor cdinter=(ClassDescriptor) interit.next();
177 tovisit.push(cdinter);
182 void processFlatMethod(MethodDescriptor md) {
183 if (!callMap.containsKey(md))
184 callMap.put(md, new HashSet<MethodDescriptor>());
186 FlatMethod fm=state.getMethodFlat(md);
187 for(FlatNode fn:fm.getNodeSet()) {
189 case FKind.FlatCall: {
190 FlatCall fcall=(FlatCall)fn;
191 processCall(md, fcall);
194 case FKind.FlatNew: {
195 FlatNew fnew=(FlatNew)fn;
203 public static ParseNode readSourceFile(State state, String sourcefile) {
205 Reader fr= new BufferedReader(new FileReader(sourcefile));
206 Lex.Lexer l = new Lex.Lexer(fr);
207 java_cup.runtime.lr_parser g;
208 g = new Parse.Parser(l);
211 p=(ParseNode) g./*debug_*/parse().value;
212 } catch (Exception e) {
213 System.err.println("Error parsing file:"+sourcefile);
217 state.addParseNode(p);
218 if (l.numErrors()!=0) {
219 System.out.println("Error parsing "+sourcefile);
220 System.exit(l.numErrors());
222 state.lines+=l.line_num;
225 } catch (Exception e) {
230 public void loadClass(BuildIR bir, String sourcefile) {
232 ParseNode pn=readSourceFile(state, sourcefile);
233 bir.buildtree(pn, null,sourcefile);
234 } catch (Exception e) {
235 System.out.println("Error in sourcefile:"+sourcefile);
239 System.out.println("Error in sourcefile:"+sourcefile);