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