1 package polyglot.visit; 2 3 import java.util.Stack ; 4 5 import polyglot.ast.Node; 6 import polyglot.ast.NodeFactory; 7 import polyglot.frontend.Job; 8 import polyglot.main.Report; 9 import polyglot.types.*; 10 import polyglot.types.Package; 11 import polyglot.util.*; 12 13 14 public class TypeBuilder extends HaltingVisitor 15 { 16 protected ImportTable importTable; 17 protected Job job; 18 protected TypeSystem ts; 19 protected NodeFactory nf; 20 protected TypeBuilder outer; 21 protected boolean inCode; protected boolean global; protected ParsedClassType type; 25 public TypeBuilder(Job job, TypeSystem ts, NodeFactory nf) { 26 this.job = job; 27 this.ts = ts; 28 this.nf = nf; 29 this.outer = null; 30 } 31 32 public TypeBuilder push() { 33 TypeBuilder tb = (TypeBuilder) this.copy(); 34 tb.outer = this; 35 return tb; 36 } 37 38 public TypeBuilder pop() { 39 return outer; 40 } 41 42 public Job job() { 43 return job; 44 } 45 46 public ErrorQueue errorQueue() { 47 return job.compiler().errorQueue(); 48 } 49 50 public NodeFactory nodeFactory() { 51 return nf; 52 } 53 54 public TypeSystem typeSystem() { 55 return ts; 56 } 57 58 public NodeVisitor begin() { 59 Context context = job.context(); 61 62 if (context == null) { 63 return this; 64 } 65 66 Stack s = new Stack (); 67 68 for (ParsedClassType ct = context.currentClassScope(); ct != null; ) { 69 s.push(ct); 70 71 if (ct.isNested()) { 72 ct = (ParsedClassType) ct.outer(); 73 } 74 else { 75 ct = null; 76 } 77 } 78 79 if (context.importTable() != null) { 80 setImportTable(context.importTable()); 81 } 82 83 TypeBuilder tb = this; 84 85 while (! s.isEmpty()) { 86 ParsedClassType ct = (ParsedClassType) s.pop(); 87 88 try { 89 tb = tb.pushClass(ct); 90 } 91 catch (SemanticException e) { 92 errorQueue().enqueue(ErrorInfo.SEMANTIC_ERROR, 93 e.getMessage(), ct.position()); 94 return null; 95 } 96 97 if (ct.isLocal() || ct.isAnonymous()) { 98 tb = tb.pushCode(); 99 } 100 } 101 102 return tb; 103 } 104 105 public NodeVisitor enter(Node n) { 106 try { 107 return n.del().buildTypesEnter(this); 108 } 109 catch (SemanticException e) { 110 Position position = e.position(); 111 112 if (position == null) { 113 position = n.position(); 114 } 115 116 if (e.getMessage() != null) { 117 errorQueue().enqueue(ErrorInfo.SEMANTIC_ERROR, 118 e.getMessage(), position); 119 } 120 121 return this; 122 } 123 } 124 125 public Node leave(Node old, Node n, NodeVisitor v) { 126 try { 127 return n.del().buildTypes((TypeBuilder) v); 128 } 129 catch (SemanticException e) { 130 Position position = e.position(); 131 132 if (position == null) { 133 position = n.position(); 134 } 135 136 if (e.getMessage() != null) { 137 errorQueue().enqueue(ErrorInfo.SEMANTIC_ERROR, 138 e.getMessage(), position); 139 } 140 141 return n; 142 } 143 } 144 145 public TypeBuilder pushCode() { 146 if (Report.should_report(Report.visit, 4)) 147 Report.report(4, "TB pushing code: " + this); 148 TypeBuilder tb = push(); 149 tb.inCode = true; 150 tb.global = false; 151 return tb; 152 } 153 154 protected TypeBuilder pushClass(ParsedClassType type) throws SemanticException { 155 if (Report.should_report(Report.visit, 4)) 156 Report.report(4, "TB pushing class " + type + ": " + this); 157 158 TypeBuilder tb = push(); 159 tb.type = type; 160 tb.inCode = false; 161 162 if (importTable() != null && type.isTopLevel()) { 164 tb.importTable().addClassImport(type.fullName()); 165 } 166 167 return tb; 168 } 169 170 protected ParsedClassType newClass(Position pos, Flags flags, String name) 171 throws SemanticException 172 { 173 TypeSystem ts = typeSystem(); 174 175 ParsedClassType ct = ts.createClassType(this.job.source()); 176 177 if (inCode) { 178 ct.kind(ClassType.LOCAL); 179 ct.outer(currentClass()); 180 ct.flags(flags); 181 ct.name(name); 182 ct.position(pos); 183 184 if (currentPackage() != null) { 185 ct.package_(currentPackage()); 186 } 187 188 return ct; 189 } 190 else if (currentClass() != null) { 191 ct.kind(ClassType.MEMBER); 192 ct.outer(currentClass()); 193 ct.flags(flags); 194 ct.name(name); 195 ct.position(pos); 196 197 currentClass().addMemberClass(ct); 198 199 if (currentPackage() != null) { 200 ct.package_(currentPackage()); 201 } 202 203 ClassType container = ct.outer(); 207 boolean allMembers = (container.isMember() || container.isTopLevel()); 208 while (container.isMember()) { 209 container = container.outer(); 210 allMembers = allMembers && 211 (container.isMember() || container.isTopLevel()); 212 } 213 214 if (allMembers) { 215 typeSystem().parsedResolver().addNamed( 216 typeSystem().getTransformedClassName(ct), ct); 217 } 218 219 return ct; 220 } 221 else { 222 ct.kind(ClassType.TOP_LEVEL); 223 ct.flags(flags); 224 ct.name(name); 225 ct.position(pos); 226 227 if (currentPackage() != null) { 228 ct.package_(currentPackage()); 229 } 230 231 Named dup = ((CachingResolver) typeSystem().systemResolver()).check(ct.fullName()); 232 233 if (dup != null && dup.fullName().equals(ct.fullName())) { 234 throw new SemanticException("Duplicate class \"" + 235 ct.fullName() + "\".", pos); 236 } 237 238 typeSystem().parsedResolver().addNamed(ct.fullName(), ct); 239 ((CachingResolver) typeSystem().systemResolver()).addNamed(ct.fullName(), ct); 240 241 return ct; 242 } 243 } 244 245 public TypeBuilder pushAnonClass(Position pos) throws SemanticException { 246 if (Report.should_report(Report.visit, 4)) 247 Report.report(4, "TB pushing anon class: " + this); 248 249 if (! inCode) { 250 throw new InternalCompilerError( 251 "Can only push an anonymous class within code."); 252 } 253 254 TypeSystem ts = typeSystem(); 255 256 ParsedClassType ct = ts.createClassType(this.job().source()); 257 ct.kind(ClassType.ANONYMOUS); 258 ct.outer(currentClass()); 259 ct.position(pos); 260 261 if (currentPackage() != null) { 262 ct.package_(currentPackage()); 263 } 264 265 return pushClass(ct); 266 } 267 268 public TypeBuilder pushClass(Position pos, Flags flags, String name) 269 throws SemanticException { 270 271 ParsedClassType t = newClass(pos, flags, name); 272 return pushClass(t); 273 } 274 275 public ParsedClassType currentClass() { 276 return this.type; 277 } 278 279 public Package currentPackage() { 280 if (importTable() == null) return null; 281 return importTable.package_(); 282 } 283 284 public ImportTable importTable() { 285 return importTable; 286 } 287 288 public void setImportTable(ImportTable it) { 289 this.importTable = it; 290 } 291 292 public String toString() { 293 return "(TB " + type + 294 (inCode ? " inCode" : "") + 295 (global ? " global" : "") + 296 (outer == null ? ")" : " " + outer.toString() + ")"); 297 } 298 } 299 | Popular Tags |