1 package polyglot.ext.jl.ast; 2 3 import polyglot.ast.*; 4 import polyglot.types.*; 5 import polyglot.util.*; 6 import polyglot.visit.*; 7 import java.util.*; 8 9 15 public class Call_c extends Expr_c implements Call 16 { 17 protected Receiver target; 18 protected String name; 19 protected List arguments; 20 protected MethodInstance mi; 21 protected boolean targetImplicit; 22 23 public Call_c(Position pos, Receiver target, String name, 24 List arguments) { 25 super(pos); 26 this.target = target; 27 this.name = name; 28 this.arguments = TypedList.copyAndCheck(arguments, Expr.class, true); 29 this.targetImplicit = (target == null); 30 } 31 32 33 public Precedence precedence() { 34 return Precedence.LITERAL; 35 } 36 37 38 public Receiver target() { 39 return this.target; 40 } 41 42 43 public Call target(Receiver target) { 44 Call_c n = (Call_c) copy(); 45 n.target = target; 46 return n; 47 } 48 49 50 public String name() { 51 return this.name; 52 } 53 54 55 public Call name(String name) { 56 Call_c n = (Call_c) copy(); 57 n.name = name; 58 return n; 59 } 60 61 public ProcedureInstance procedureInstance() { 62 return methodInstance(); 63 } 64 65 66 public MethodInstance methodInstance() { 67 return this.mi; 68 } 69 70 71 public Call methodInstance(MethodInstance mi) { 72 Call_c n = (Call_c) copy(); 73 n.mi = mi; 74 return n; 75 } 76 77 public boolean isTargetImplicit() { 78 return this.targetImplicit; 79 } 80 81 public Call targetImplicit(boolean targetImplicit) { 82 if (targetImplicit == this.targetImplicit) { 83 return this; 84 } 85 86 Call_c n = (Call_c) copy(); 87 n.targetImplicit = targetImplicit; 88 return n; 89 } 90 91 92 public List arguments() { 93 return this.arguments; 94 } 95 96 97 public ProcedureCall arguments(List arguments) { 98 Call_c n = (Call_c) copy(); 99 n.arguments = TypedList.copyAndCheck(arguments, Expr.class, true); 100 return n; 101 } 102 103 104 protected Call_c reconstruct(Receiver target, List arguments) { 105 if (target != this.target || ! CollectionUtil.equals(arguments, 106 this.arguments)) { 107 Call_c n = (Call_c) copy(); 108 n.target = target; 109 n.arguments = TypedList.copyAndCheck(arguments, Expr.class, true); 110 return n; 111 } 112 113 return this; 114 } 115 116 117 public Node visitChildren(NodeVisitor v) { 118 Receiver target = (Receiver) visitChild(this.target, v); 119 List arguments = visitList(this.arguments, v); 120 return reconstruct(target, arguments); 121 } 122 123 public Node buildTypes(TypeBuilder tb) throws SemanticException { 124 Call_c n = (Call_c) super.buildTypes(tb); 125 126 TypeSystem ts = tb.typeSystem(); 127 128 List l = new ArrayList(arguments.size()); 129 for (int i = 0; i < arguments.size(); i++) { 130 l.add(ts.unknownType(position())); 131 } 132 133 MethodInstance mi = ts.methodInstance(position(), ts.Object(), 134 Flags.NONE, 135 ts.unknownType(position()), 136 name, l, 137 Collections.EMPTY_LIST); 138 return n.methodInstance(mi); 139 } 140 141 147 protected Node typeCheckNullTarget(TypeChecker tc, List argTypes) throws SemanticException { 148 TypeSystem ts = tc.typeSystem(); 149 NodeFactory nf = tc.nodeFactory(); 150 Context c = tc.context(); 151 152 MethodInstance mi = c.findMethod(this.name, argTypes); 157 158 Receiver r; 159 if (mi.flags().isStatic()) { 160 r = nf.CanonicalTypeNode(position(), mi.container()).type(mi.container()); 161 } else { 162 ClassType scope = c.findMethodScope(name); 168 169 if (! ts.equals(scope, c.currentClass())) { 170 r = nf.This(position(), 171 nf.CanonicalTypeNode(position(), scope)).type(scope); 172 } 173 else { 174 r = nf.This(position()).type(scope); 175 } 176 } 177 178 r = (Receiver)r.typeCheck(tc); 180 return this.targetImplicit(true).target(r).del().typeCheck(tc); 181 } 182 183 184 public Node typeCheck(TypeChecker tc) throws SemanticException { 185 TypeSystem ts = tc.typeSystem(); 186 Context c = tc.context(); 187 188 List argTypes = new ArrayList(this.arguments.size()); 189 190 for (Iterator i = this.arguments.iterator(); i.hasNext(); ) { 191 Expr e = (Expr) i.next(); 192 argTypes.add(e.type()); 193 } 194 195 if (this.target == null) { 196 return this.typeCheckNullTarget(tc, argTypes); 197 } 198 199 ReferenceType targetType = this.findTargetType(); 200 MethodInstance mi = ts.findMethod(targetType, 201 this.name, 202 argTypes, 203 c.currentClass()); 204 205 206 209 boolean staticContext = (this.target instanceof TypeNode); 210 211 212 if (staticContext && !mi.flags().isStatic()) { 213 throw new SemanticException("Cannot call non-static method " + this.name 214 + " of " + targetType + " in static " 215 + "context.", this.position()); 216 } 217 218 if (this.target instanceof Special && 220 ((Special)this.target).kind() == Special.SUPER && 221 mi.flags().isAbstract()) { 222 throw new SemanticException("Cannot call an abstract method " + 223 "of the super class", this.position()); 224 } 225 228 Call_c call = (Call_c)this.methodInstance(mi).type(mi.returnType()); 229 call.checkConsistency(c); 230 return call; 231 } 232 233 protected ReferenceType findTargetType() throws SemanticException { 234 Type t = target.type(); 235 if (t.isReference()) { 236 return t.toReference(); 237 } else { 238 if (target instanceof Expr) { 241 throw new SemanticException("Cannot invoke method \"" + name + "\" on " 242 + "an expression of non-reference type " 243 + t + ".", target.position()); 244 } 245 else if (target instanceof TypeNode) { 246 throw new SemanticException("Cannot invoke static method \"" + name 247 + "\" on non-reference type " + t + ".", 248 target.position()); 249 } 250 throw new SemanticException("Receiver of method invocation must be a " 251 + "reference type.", 252 target.position()); 253 } 254 } 255 256 public Type childExpectedType(Expr child, AscriptionVisitor av) 257 { 258 if (child == target) { 259 return mi.container(); 260 } 261 262 Iterator i = this.arguments.iterator(); 263 Iterator j = mi.formalTypes().iterator(); 264 265 while (i.hasNext() && j.hasNext()) { 266 Expr e = (Expr) i.next(); 267 Type t = (Type) j.next(); 268 269 if (e == child) { 270 return t; 271 } 272 } 273 274 return child.type(); 275 } 276 277 public String toString() { 278 StringBuffer sb = new StringBuffer (); 279 sb.append(targetImplicit ? "" : target.toString() + "."); 280 sb.append(name); 281 sb.append("("); 282 283 int count = 0; 284 285 for (Iterator i = arguments.iterator(); i.hasNext(); ) { 286 if (count++ > 2) { 287 sb.append("..."); 288 break; 289 } 290 291 Expr n = (Expr) i.next(); 292 sb.append(n.toString()); 293 294 if (i.hasNext()) { 295 sb.append(", "); 296 } 297 } 298 299 sb.append(")"); 300 return sb.toString(); 301 } 302 303 304 public void prettyPrint(CodeWriter w, PrettyPrinter tr) { 305 if (!targetImplicit) { 306 if (target instanceof Expr) { 307 printSubExpr((Expr) target, w, tr); 308 w.write("."); 309 } 310 else if (target != null) { 311 print(target, w, tr); 312 w.write("."); 313 } 314 } 315 316 w.write(name + "("); 317 w.begin(0); 318 319 for(Iterator i = arguments.iterator(); i.hasNext();) { 320 Expr e = (Expr) i.next(); 321 print(e, w, tr); 322 323 if (i.hasNext()) { 324 w.write(","); 325 w.allowBreak(0, " "); 326 } 327 } 328 329 w.end(); 330 w.write(")"); 331 } 332 333 334 public void dump(CodeWriter w) { 335 super.dump(w); 336 337 if ( mi != null ) { 338 w.allowBreak(4, " "); 339 w.begin(0); 340 w.write("(instance " + mi + ")"); 341 w.end(); 342 } 343 344 w.allowBreak(4, " "); 345 w.begin(0); 346 w.write("(name " + name + ")"); 347 w.end(); 348 349 w.allowBreak(4, " "); 350 w.begin(0); 351 w.write("(arguments " + arguments + ")"); 352 w.end(); 353 } 354 355 public Term entry() { 356 if (target instanceof Expr) { 357 return ((Expr) target).entry(); 358 } 359 return listEntry(arguments, this); 360 } 361 362 public List acceptCFG(CFGBuilder v, List succs) { 363 if (target instanceof Expr) { 364 Expr t = (Expr) target; 365 v.visitCFG(t, listEntry(arguments, this)); 366 } 367 368 v.visitCFGList(arguments, this); 369 370 return succs; 371 } 372 373 374 public Node exceptionCheck(ExceptionChecker ec) throws SemanticException { 375 if (mi == null) { 376 throw new InternalCompilerError(position(), 377 "Null method instance after type " 378 + "check."); 379 } 380 381 return super.exceptionCheck(ec); 382 } 383 384 385 public List throwTypes(TypeSystem ts) { 386 List l = new LinkedList(); 387 388 l.addAll(mi.throwTypes()); 389 l.addAll(ts.uncheckedExceptions()); 390 391 if (target instanceof Expr && ! (target instanceof Special)) { 392 l.add(ts.NullPointerException()); 393 } 394 395 return l; 396 } 397 398 protected void checkConsistency(Context c) throws SemanticException { 400 if (targetImplicit) { 401 405 MethodInstance ctxtMI = c.findMethod(name, mi.formalTypes()); 408 409 } 417 } 418 419 } 420 | Popular Tags |