1 package polyglot.ext.jl.ast; 2 3 import java.util.*; 4 5 import polyglot.ast.*; 6 import polyglot.types.*; 7 import polyglot.util.CodeWriter; 8 import polyglot.util.CollectionUtil; 9 import polyglot.util.Position; 10 import polyglot.util.SubtypeSet; 11 import polyglot.util.TypedList; 12 import polyglot.visit.*; 13 14 18 public class ConstructorDecl_c extends Term_c implements ConstructorDecl 19 { 20 protected Flags flags; 21 protected String name; 22 protected List formals; 23 protected List throwTypes; 24 protected Block body; 25 protected ConstructorInstance ci; 26 27 public ConstructorDecl_c(Position pos, Flags flags, String name, List formals, List throwTypes, Block body) { 28 super(pos); 29 this.flags = flags; 30 this.name = name; 31 this.formals = TypedList.copyAndCheck(formals, Formal.class, true); 32 this.throwTypes = TypedList.copyAndCheck(throwTypes, TypeNode.class, true); 33 this.body = body; 34 } 35 36 37 public Flags flags() { 38 return this.flags; 39 } 40 41 42 public ConstructorDecl flags(Flags flags) { 43 ConstructorDecl_c n = (ConstructorDecl_c) copy(); 44 n.flags = flags; 45 return n; 46 } 47 48 49 public String name() { 50 return this.name; 51 } 52 53 54 public ConstructorDecl name(String name) { 55 ConstructorDecl_c n = (ConstructorDecl_c) copy(); 56 n.name = name; 57 return n; 58 } 59 60 61 public List formals() { 62 return Collections.unmodifiableList(this.formals); 63 } 64 65 66 public ConstructorDecl formals(List formals) { 67 ConstructorDecl_c n = (ConstructorDecl_c) copy(); 68 n.formals = TypedList.copyAndCheck(formals, Formal.class, true); 69 return n; 70 } 71 72 73 public List throwTypes() { 74 return Collections.unmodifiableList(this.throwTypes); 75 } 76 77 78 public ConstructorDecl throwTypes(List throwTypes) { 79 ConstructorDecl_c n = (ConstructorDecl_c) copy(); 80 n.throwTypes = TypedList.copyAndCheck(throwTypes, TypeNode.class, true); 81 return n; 82 } 83 84 85 public Block body() { 86 return this.body; 87 } 88 89 90 public CodeDecl body(Block body) { 91 ConstructorDecl_c n = (ConstructorDecl_c) copy(); 92 n.body = body; 93 return n; 94 } 95 96 97 public ConstructorInstance constructorInstance() { 98 return ci; 99 } 100 101 102 103 public ProcedureInstance procedureInstance() { 104 return ci; 105 } 106 107 public CodeInstance codeInstance() { 108 return procedureInstance(); 109 } 110 111 112 public ConstructorDecl constructorInstance(ConstructorInstance ci) { 113 ConstructorDecl_c n = (ConstructorDecl_c) copy(); 114 n.ci = ci; 115 return n; 116 } 117 118 119 protected ConstructorDecl_c reconstruct(List formals, List throwTypes, Block body) { 120 if (! CollectionUtil.equals(formals, this.formals) || ! CollectionUtil.equals(throwTypes, this.throwTypes) || body != this.body) { 121 ConstructorDecl_c n = (ConstructorDecl_c) copy(); 122 n.formals = TypedList.copyAndCheck(formals, Formal.class, true); 123 n.throwTypes = TypedList.copyAndCheck(throwTypes, TypeNode.class, true); 124 n.body = body; 125 return n; 126 } 127 128 return this; 129 } 130 131 132 public Node visitChildren(NodeVisitor v) { 133 List formals = visitList(this.formals, v); 134 List throwTypes = visitList(this.throwTypes, v); 135 Block body = (Block) visitChild(this.body, v); 136 return reconstruct(formals, throwTypes, body); 137 } 138 139 public NodeVisitor buildTypesEnter(TypeBuilder tb) throws SemanticException { 140 return tb.pushCode(); 141 } 142 143 public Node buildTypes(TypeBuilder tb) throws SemanticException { 144 TypeSystem ts = tb.typeSystem(); 145 146 List l = new ArrayList(formals.size()); 147 for (int i = 0; i < formals.size(); i++) { 148 l.add(ts.unknownType(position())); 149 } 150 151 List m = new ArrayList(throwTypes().size()); 152 for (int i = 0; i < throwTypes().size(); i++) { 153 m.add(ts.unknownType(position())); 154 } 155 156 ConstructorInstance ci = ts.constructorInstance(position(), ts.Object(), 157 Flags.NONE, l, m); 158 return constructorInstance(ci); 159 } 160 161 public NodeVisitor disambiguateEnter(AmbiguityRemover ar) throws SemanticException { 162 if (ar.kind() == AmbiguityRemover.SUPER) { 163 return ar.bypassChildren(this); 164 } 165 else if (ar.kind() == AmbiguityRemover.SIGNATURES) { 166 if (body != null) { 167 return ar.bypass(body); 168 } 169 } 170 171 return ar; 172 } 173 174 public Node disambiguate(AmbiguityRemover ar) throws SemanticException { 175 if (ar.kind() == AmbiguityRemover.SIGNATURES) { 176 Context c = ar.context(); 177 TypeSystem ts = ar.typeSystem(); 178 179 ParsedClassType ct = c.currentClassScope(); 180 181 ConstructorInstance ci = makeConstructorInstance(ct, ts); 182 183 return constructorInstance(ci); 184 } 185 186 return this; 187 } 188 189 public NodeVisitor addMembersEnter(AddMemberVisitor am) { 190 ParsedClassType ct = am.context().currentClassScope(); 191 ct.addConstructor(ci); 192 return am.bypassChildren(this); 193 } 194 195 public Context enterScope(Context c) { 196 return c.pushCode(ci); 197 } 198 199 200 public Node typeCheck(TypeChecker tc) throws SemanticException { 201 Context c = tc.context(); 202 TypeSystem ts = tc.typeSystem(); 203 204 ClassType ct = c.currentClass(); 205 206 if (ct.flags().isInterface()) { 207 throw new SemanticException( 208 "Cannot declare a constructor inside an interface.", 209 position()); 210 } 211 212 if (ct.isAnonymous()) { 213 throw new SemanticException( 214 "Cannot declare a constructor inside an anonymous class.", 215 position()); 216 } 217 218 String ctName = ct.name(); 219 220 if (! ctName.equals(name)) { 221 throw new SemanticException("Constructor name \"" + name + 222 "\" does not match name of containing class \"" + 223 ctName + "\".", position()); 224 } 225 226 try { 227 ts.checkConstructorFlags(flags()); 228 } 229 catch (SemanticException e) { 230 throw new SemanticException(e.getMessage(), position()); 231 } 232 233 if (body == null && ! flags().isNative()) { 234 throw new SemanticException("Missing constructor body.", 235 position()); 236 } 237 238 if (body != null && flags().isNative()) { 239 throw new SemanticException( 240 "A native constructor cannot have a body.", position()); 241 } 242 243 for (Iterator i = throwTypes().iterator(); i.hasNext(); ) { 244 TypeNode tn = (TypeNode) i.next(); 245 Type t = tn.type(); 246 if (! t.isThrowable()) { 247 throw new SemanticException("Type \"" + t + 248 "\" is not a subclass of \"" + ts.Throwable() + "\".", 249 tn.position()); 250 } 251 } 252 253 return this; 254 } 255 256 257 public Node exceptionCheck(ExceptionChecker ec) throws SemanticException { 258 TypeSystem ts = ec.typeSystem(); 259 260 SubtypeSet s = (SubtypeSet) ec.throwsSet(); 261 262 for (Iterator i = s.iterator(); i.hasNext(); ) { 263 Type t = (Type) i.next(); 264 265 boolean throwDeclared = false; 266 267 if (! t.isUncheckedException()) { 268 for (Iterator j = throwTypes().iterator(); j.hasNext(); ) { 269 TypeNode tn = (TypeNode) j.next(); 270 Type tj = tn.type(); 271 272 if (ts.isSubtype(t, tj)) { 273 throwDeclared = true; 274 break; 275 } 276 } 277 278 if (! throwDeclared) { 279 ec.throwsSet().clear(); 280 Position pos = ec.exceptionPosition(t); 281 throw new SemanticException("The exception \"" + t + 282 "\" must either be caught or declared to be thrown.", 283 pos==null?position():pos); 284 } 285 } 286 } 287 288 ec.throwsSet().clear(); 289 290 return super.exceptionCheck(ec); 291 } 292 293 public String toString() { 294 return flags.translate() + name + "(...)"; 295 } 296 297 298 public void prettyPrintHeader(CodeWriter w, PrettyPrinter tr) { 299 w.begin(0); 300 w.write(flags().translate()); 301 302 w.write(name); 303 w.write("("); 304 305 w.begin(0); 306 307 for (Iterator i = formals.iterator(); i.hasNext(); ) { 308 Formal f = (Formal) i.next(); 309 print(f, w, tr); 310 311 if (i.hasNext()) { 312 w.write(","); 313 w.allowBreak(0, " "); 314 } 315 } 316 317 w.end(); 318 w.write(")"); 319 320 if (! throwTypes().isEmpty()) { 321 w.allowBreak(6); 322 w.write("throws "); 323 324 for (Iterator i = throwTypes().iterator(); i.hasNext(); ) { 325 TypeNode tn = (TypeNode) i.next(); 326 print(tn, w, tr); 327 328 if (i.hasNext()) { 329 w.write(","); 330 w.allowBreak(4, " "); 331 } 332 } 333 } 334 335 w.end(); 336 } 337 338 public void prettyPrint(CodeWriter w, PrettyPrinter tr) { 339 prettyPrintHeader(w, tr); 340 341 if (body != null) { 342 printSubStmt(body, w, tr); 343 } 344 else { 345 w.write(";"); 346 } 347 } 348 349 public void dump(CodeWriter w) { 350 super.dump(w); 351 352 if (ci != null) { 353 w.allowBreak(4, " "); 354 w.begin(0); 355 w.write("(instance " + ci + ")"); 356 w.end(); 357 } 358 } 359 360 protected ConstructorInstance makeConstructorInstance(ClassType ct, 361 TypeSystem ts) throws SemanticException { 362 363 List argTypes = new LinkedList(); 364 List excTypes = new LinkedList(); 365 366 for (Iterator i = formals.iterator(); i.hasNext(); ) { 367 Formal f = (Formal) i.next(); 368 argTypes.add(f.declType()); 369 } 370 371 for (Iterator i = throwTypes().iterator(); i.hasNext(); ) { 372 TypeNode tn = (TypeNode) i.next(); 373 excTypes.add(tn.type()); 374 } 375 376 return ts.constructorInstance(position(), ct, flags, 377 argTypes, excTypes); 378 } 379 380 384 public Term entry() { 385 return listEntry(formals(), (body()==null? this : body().entry())); 386 } 387 388 391 public List acceptCFG(CFGBuilder v, List succs) { 392 if (body() == null) { 393 v.visitCFGList(formals(), this); 394 } 395 else { 396 v.visitCFGList(formals(), body().entry()); 397 v.visitCFG(body(), this); 398 } 399 return succs; 400 } 401 402 } 403 | Popular Tags |