1 16 package com.google.gwt.dev.jjs.impl; 17 18 import com.google.gwt.dev.jjs.InternalCompilerException; 19 import com.google.gwt.dev.jjs.SourceInfo; 20 import com.google.gwt.dev.jjs.ast.CanBeStatic; 21 import com.google.gwt.dev.jjs.ast.HasEnclosingType; 22 import com.google.gwt.dev.jjs.ast.HasName; 23 import com.google.gwt.dev.jjs.ast.JArrayRef; 24 import com.google.gwt.dev.jjs.ast.JArrayType; 25 import com.google.gwt.dev.jjs.ast.JAssertStatement; 26 import com.google.gwt.dev.jjs.ast.JBinaryOperation; 27 import com.google.gwt.dev.jjs.ast.JBinaryOperator; 28 import com.google.gwt.dev.jjs.ast.JBlock; 29 import com.google.gwt.dev.jjs.ast.JBooleanLiteral; 30 import com.google.gwt.dev.jjs.ast.JBreakStatement; 31 import com.google.gwt.dev.jjs.ast.JCaseStatement; 32 import com.google.gwt.dev.jjs.ast.JCastOperation; 33 import com.google.gwt.dev.jjs.ast.JCharLiteral; 34 import com.google.gwt.dev.jjs.ast.JClassType; 35 import com.google.gwt.dev.jjs.ast.JConditional; 36 import com.google.gwt.dev.jjs.ast.JContinueStatement; 37 import com.google.gwt.dev.jjs.ast.JDoStatement; 38 import com.google.gwt.dev.jjs.ast.JDoubleLiteral; 39 import com.google.gwt.dev.jjs.ast.JExpression; 40 import com.google.gwt.dev.jjs.ast.JField; 41 import com.google.gwt.dev.jjs.ast.JFieldRef; 42 import com.google.gwt.dev.jjs.ast.JFloatLiteral; 43 import com.google.gwt.dev.jjs.ast.JForStatement; 44 import com.google.gwt.dev.jjs.ast.JIfStatement; 45 import com.google.gwt.dev.jjs.ast.JInstanceOf; 46 import com.google.gwt.dev.jjs.ast.JIntLiteral; 47 import com.google.gwt.dev.jjs.ast.JLabel; 48 import com.google.gwt.dev.jjs.ast.JLabeledStatement; 49 import com.google.gwt.dev.jjs.ast.JLiteral; 50 import com.google.gwt.dev.jjs.ast.JLocal; 51 import com.google.gwt.dev.jjs.ast.JLocalDeclarationStatement; 52 import com.google.gwt.dev.jjs.ast.JLocalRef; 53 import com.google.gwt.dev.jjs.ast.JLongLiteral; 54 import com.google.gwt.dev.jjs.ast.JMethod; 55 import com.google.gwt.dev.jjs.ast.JMethodCall; 56 import com.google.gwt.dev.jjs.ast.JNewArray; 57 import com.google.gwt.dev.jjs.ast.JNewInstance; 58 import com.google.gwt.dev.jjs.ast.JNode; 59 import com.google.gwt.dev.jjs.ast.JParameter; 60 import com.google.gwt.dev.jjs.ast.JParameterRef; 61 import com.google.gwt.dev.jjs.ast.JPostfixOperation; 62 import com.google.gwt.dev.jjs.ast.JPrefixOperation; 63 import com.google.gwt.dev.jjs.ast.JProgram; 64 import com.google.gwt.dev.jjs.ast.JReferenceType; 65 import com.google.gwt.dev.jjs.ast.JReturnStatement; 66 import com.google.gwt.dev.jjs.ast.JStatement; 67 import com.google.gwt.dev.jjs.ast.JStringLiteral; 68 import com.google.gwt.dev.jjs.ast.JSwitchStatement; 69 import com.google.gwt.dev.jjs.ast.JThrowStatement; 70 import com.google.gwt.dev.jjs.ast.JTryStatement; 71 import com.google.gwt.dev.jjs.ast.JType; 72 import com.google.gwt.dev.jjs.ast.JUnaryOperator; 73 import com.google.gwt.dev.jjs.ast.JVariable; 74 import com.google.gwt.dev.jjs.ast.JVariableRef; 75 import com.google.gwt.dev.jjs.ast.JWhileStatement; 76 import com.google.gwt.dev.jjs.ast.js.JsniFieldRef; 77 import com.google.gwt.dev.jjs.ast.js.JsniMethod; 78 import com.google.gwt.dev.jjs.ast.js.JsniMethodRef; 79 import com.google.gwt.dev.js.ast.JsContext; 80 import com.google.gwt.dev.js.ast.JsFunction; 81 import com.google.gwt.dev.js.ast.JsNameRef; 82 import com.google.gwt.dev.js.ast.JsSourceInfo; 83 import com.google.gwt.dev.js.ast.JsVisitor; 84 85 import org.eclipse.jdt.core.compiler.IProblem; 86 import org.eclipse.jdt.internal.compiler.CompilationResult; 87 import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression; 88 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; 89 import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; 90 import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression; 91 import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; 92 import org.eclipse.jdt.internal.compiler.ast.ArrayReference; 93 import org.eclipse.jdt.internal.compiler.ast.AssertStatement; 94 import org.eclipse.jdt.internal.compiler.ast.Assignment; 95 import org.eclipse.jdt.internal.compiler.ast.BinaryExpression; 96 import org.eclipse.jdt.internal.compiler.ast.Block; 97 import org.eclipse.jdt.internal.compiler.ast.BreakStatement; 98 import org.eclipse.jdt.internal.compiler.ast.CaseStatement; 99 import org.eclipse.jdt.internal.compiler.ast.CastExpression; 100 import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess; 101 import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment; 102 import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression; 103 import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; 104 import org.eclipse.jdt.internal.compiler.ast.ContinueStatement; 105 import org.eclipse.jdt.internal.compiler.ast.DoStatement; 106 import org.eclipse.jdt.internal.compiler.ast.EmptyStatement; 107 import org.eclipse.jdt.internal.compiler.ast.EqualExpression; 108 import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; 109 import org.eclipse.jdt.internal.compiler.ast.Expression; 110 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; 111 import org.eclipse.jdt.internal.compiler.ast.FieldReference; 112 import org.eclipse.jdt.internal.compiler.ast.ForStatement; 113 import org.eclipse.jdt.internal.compiler.ast.IfStatement; 114 import org.eclipse.jdt.internal.compiler.ast.Initializer; 115 import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression; 116 import org.eclipse.jdt.internal.compiler.ast.LabeledStatement; 117 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; 118 import org.eclipse.jdt.internal.compiler.ast.MessageSend; 119 import org.eclipse.jdt.internal.compiler.ast.NullLiteral; 120 import org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression; 121 import org.eclipse.jdt.internal.compiler.ast.PostfixExpression; 122 import org.eclipse.jdt.internal.compiler.ast.PrefixExpression; 123 import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression; 124 import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; 125 import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference; 126 import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference; 127 import org.eclipse.jdt.internal.compiler.ast.ReturnStatement; 128 import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; 129 import org.eclipse.jdt.internal.compiler.ast.Statement; 130 import org.eclipse.jdt.internal.compiler.ast.SuperReference; 131 import org.eclipse.jdt.internal.compiler.ast.SwitchStatement; 132 import org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement; 133 import org.eclipse.jdt.internal.compiler.ast.ThisReference; 134 import org.eclipse.jdt.internal.compiler.ast.ThrowStatement; 135 import org.eclipse.jdt.internal.compiler.ast.TryStatement; 136 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; 137 import org.eclipse.jdt.internal.compiler.ast.UnaryExpression; 138 import org.eclipse.jdt.internal.compiler.ast.WhileStatement; 139 import org.eclipse.jdt.internal.compiler.impl.BooleanConstant; 140 import org.eclipse.jdt.internal.compiler.impl.ByteConstant; 141 import org.eclipse.jdt.internal.compiler.impl.CharConstant; 142 import org.eclipse.jdt.internal.compiler.impl.Constant; 143 import org.eclipse.jdt.internal.compiler.impl.DoubleConstant; 144 import org.eclipse.jdt.internal.compiler.impl.FloatConstant; 145 import org.eclipse.jdt.internal.compiler.impl.IntConstant; 146 import org.eclipse.jdt.internal.compiler.impl.LongConstant; 147 import org.eclipse.jdt.internal.compiler.impl.ShortConstant; 148 import org.eclipse.jdt.internal.compiler.impl.StringConstant; 149 import org.eclipse.jdt.internal.compiler.lookup.Binding; 150 import org.eclipse.jdt.internal.compiler.lookup.ClassScope; 151 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; 152 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; 153 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; 154 import org.eclipse.jdt.internal.compiler.lookup.MethodScope; 155 import org.eclipse.jdt.internal.compiler.lookup.NestedTypeBinding; 156 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; 157 import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; 158 import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding; 159 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; 160 import org.eclipse.jdt.internal.compiler.lookup.VariableBinding; 161 import org.eclipse.jdt.internal.compiler.problem.DefaultProblem; 162 import org.eclipse.jdt.internal.compiler.problem.ProblemHandler; 163 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; 164 165 import java.lang.reflect.InvocationTargetException ; 166 import java.lang.reflect.Method ; 167 import java.util.ArrayList ; 168 import java.util.Collections ; 169 import java.util.HashMap ; 170 import java.util.IdentityHashMap ; 171 import java.util.Iterator ; 172 import java.util.LinkedList ; 173 import java.util.List ; 174 import java.util.Map ; 175 176 181 public class GenerateJavaAST { 182 183 202 private static class JavaASTGenerationVisitor { 203 204 private static String getJsniSig(JMethod method) { 205 StringBuffer sb = new StringBuffer (); 206 sb.append(method.getName()); 207 sb.append("("); 208 for (int i = 0; i < method.getOriginalParamTypes().size(); ++i) { 209 JType type = (JType) method.getOriginalParamTypes().get(i); 210 sb.append(type.getJsniSignatureName()); 211 } 212 sb.append(")"); 213 return sb.toString(); 214 } 215 216 private static InternalCompilerException translateException(JNode node, 217 Throwable e) { 218 InternalCompilerException ice; 219 if (e instanceof InternalCompilerException) { 220 ice = (InternalCompilerException) e; 221 ice.addNode(node); 222 } else { 223 ice = new InternalCompilerException(node, 224 "Error constructing Java AST", e); 225 } 226 return ice; 227 } 228 229 private Object [] args = new Object [1]; 230 231 private JReferenceType currentClass; 232 233 private ClassScope currentClassScope; 234 235 private String currentFileName; 236 237 private JMethod currentMethod; 238 239 private MethodScope currentMethodScope; 240 241 private int[] currentSeparatorPositions; 242 243 private final Map labelMap = new IdentityHashMap (); 244 245 private Class [] params = new Class [1]; 246 247 private final JProgram program; 248 249 private final TypeMap typeMap; 250 251 public JavaASTGenerationVisitor(TypeMap typeMap) { 252 this.typeMap = typeMap; 253 program = this.typeMap.getProgram(); 254 } 255 256 261 public void processType(TypeDeclaration x) { 262 currentClass = (JReferenceType) typeMap.get(x.binding); 263 try { 264 currentClassScope = x.scope; 265 currentSeparatorPositions = x.compilationResult.lineSeparatorPositions; 266 currentFileName = String.valueOf(x.compilationResult.fileName); 267 268 if (x.fields != null) { 269 for (int i = 0, n = x.fields.length; i < n; ++i) { 271 FieldDeclaration fieldDeclaration = x.fields[i]; 272 if (fieldDeclaration.isStatic()) { 273 currentMethod = (JMethod) currentClass.methods.get(0); 275 currentMethodScope = x.staticInitializerScope; 276 } else { 277 currentMethod = (JMethod) currentClass.methods.get(1); 279 currentMethodScope = x.initializerScope; 280 } 281 282 if (fieldDeclaration instanceof Initializer) { 283 assert (currentClass instanceof JClassType); 284 processInitializer((Initializer) fieldDeclaration); 285 } else { 286 processField(fieldDeclaration); 287 } 288 } 289 } 290 291 currentMethodScope = null; 292 currentMethod = null; 293 294 if (x.methods != null) { 295 for (int i = 0, n = x.methods.length; i < n; ++i) { 297 if (x.methods[i].isConstructor()) { 298 assert (currentClass instanceof JClassType); 299 processConstructor((ConstructorDeclaration) x.methods[i]); 300 } else if (x.methods[i].isClinit()) { 301 } else { 303 processMethod(x.methods[i]); 304 } 305 } 306 } 307 308 currentClassScope = null; 309 currentClass = null; 310 currentSeparatorPositions = null; 311 currentFileName = null; 312 } catch (Throwable e) { 313 throw translateException(currentClass, e); 314 } 315 } 316 317 321 protected JNode dispatch(String name, Object child) { 322 if (child == null) { 323 return null; 324 } 325 326 try { 327 params[0] = child.getClass(); 328 Method method = getClass().getDeclaredMethod(name, params); 329 args[0] = child; 330 return (JNode) method.invoke(this, args); 331 } catch (Throwable e) { 332 if (e instanceof InvocationTargetException ) { 333 e = ((InvocationTargetException ) e).getTargetException(); 334 } 335 throw translateException(child, e); 336 } 337 } 338 339 342 protected JExpression dispProcessExpression(Expression x) { 343 349 if (x != null && x.constant != null 350 && x.constant != Constant.NotAConstant) { 351 return (JExpression) dispatch("processConstant", x.constant); 352 } 353 return (JExpression) dispatch("processExpression", x); 354 } 355 356 359 protected JStatement dispProcessStatement(Statement x) { 360 JStatement stmt; 361 if (x instanceof Expression) { 362 JExpression expr = dispProcessExpression((Expression) x); 363 if (expr == null) { 364 return null; 365 } 366 stmt = expr.makeStatement(); 367 } else { 368 stmt = (JStatement) dispatch("processStatement", x); 369 } 370 return stmt; 371 } 372 373 JBooleanLiteral processConstant(BooleanConstant x) { 374 return program.getLiteralBoolean(x.booleanValue()); 375 } 376 377 JIntLiteral processConstant(ByteConstant x) { 378 return program.getLiteralInt(x.byteValue()); 379 } 380 381 JCharLiteral processConstant(CharConstant x) { 382 return program.getLiteralChar(x.charValue()); 383 } 384 385 JDoubleLiteral processConstant(DoubleConstant x) { 386 return program.getLiteralDouble(x.doubleValue()); 387 } 388 389 JFloatLiteral processConstant(FloatConstant x) { 390 return program.getLiteralFloat(x.floatValue()); 391 } 392 393 JIntLiteral processConstant(IntConstant x) { 394 return program.getLiteralInt(x.intValue()); 395 } 396 397 JLongLiteral processConstant(LongConstant x) { 398 return program.getLiteralLong(x.longValue()); 399 } 400 401 JIntLiteral processConstant(ShortConstant x) { 402 return program.getLiteralInt(x.shortValue()); 403 } 404 405 JStringLiteral processConstant(StringConstant x) { 406 return program.getLiteralString(x.stringValue().toCharArray()); 407 } 408 409 435 void processConstructor(ConstructorDeclaration x) { 436 JMethod ctor = (JMethod) typeMap.get(x.binding); 437 try { 438 SourceInfo info = ctor.body.getSourceInfo(); 439 440 currentMethod = ctor; 441 currentMethodScope = x.scope; 442 443 JMethodCall superOrThisCall = null; 444 ExplicitConstructorCall ctorCall = x.constructorCall; 445 if (ctorCall != null) { 446 superOrThisCall = (JMethodCall) dispatch("processExpression", 447 ctorCall); 448 } 449 450 457 boolean hasExplicitThis = (ctorCall != null) 458 && !ctorCall.isSuperAccess(); 459 460 JClassType enclosingType = (JClassType) ctor.getEnclosingType(); 461 462 JMethod clinitMethod = (JMethod) enclosingType.methods.get(0); 464 JMethodCall clinitCall = new JMethodCall(program, info, null, 465 clinitMethod); 466 ctor.body.statements.add(clinitCall.makeStatement()); 467 468 473 if (!hasExplicitThis) { 474 ReferenceBinding declaringClass = x.binding.declaringClass; 475 if (declaringClass instanceof NestedTypeBinding) { 476 Iterator paramIt = getSyntheticsIterator(ctor); 477 NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass; 478 if (nestedBinding.enclosingInstances != null) { 479 for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) { 480 SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i]; 481 JParameter param = (JParameter) paramIt.next(); 482 if (arg.matchingField != null) { 483 JField field = (JField) typeMap.get(arg); 484 ctor.body.statements.add(program.createAssignmentStmt(info, 485 createVariableRef(info, field), createVariableRef(info, 486 param))); 487 } 488 } 489 } 490 491 if (nestedBinding.outerLocalVariables != null) { 492 for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) { 493 SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i]; 494 JParameter param = (JParameter) paramIt.next(); 495 JField field = (JField) typeMap.get(arg); 496 ctor.body.statements.add(program.createAssignmentStmt(info, 497 createVariableRef(info, field), createVariableRef(info, 498 param))); 499 } 500 } 501 } 502 } 503 504 if (superOrThisCall != null) { 506 ctor.body.statements.add(superOrThisCall.makeStatement()); 507 } 508 509 JExpression thisRef = createThisRef(info, enclosingType); 510 511 515 if (!hasExplicitThis) { 516 JMethod initMethod = (JMethod) enclosingType.methods.get(1); 518 JMethodCall initCall = new JMethodCall(program, info, thisRef, 519 initMethod); 520 ctor.body.statements.add(initCall.makeStatement()); 521 } 522 523 if (x.statements != null) { 525 for (int i = 0, n = x.statements.length; i < n; ++i) { 526 Statement origStmt = x.statements[i]; 527 JStatement jstmt = dispProcessStatement(origStmt); 528 if (jstmt != null) { 529 ctor.body.statements.add(jstmt); 530 } 531 } 532 } 533 534 currentMethodScope = null; 535 currentMethod = null; 536 537 ctor.body.statements.add(new JReturnStatement(program, null, thisRef)); 539 } catch (Throwable e) { 540 throw translateException(ctor, e); 541 } 542 } 543 544 JExpression processExpression(AllocationExpression x) { 545 SourceInfo info = makeSourceInfo(x); 546 SourceTypeBinding typeBinding = (SourceTypeBinding) x.resolvedType; 547 if (typeBinding.constantPoolName() == null) { 548 552 return program.getLiteralNull(); 553 } 554 JClassType newType = (JClassType) typeMap.get(typeBinding); 555 MethodBinding b = x.binding; 556 JMethod ctor = (JMethod) typeMap.get(b); 557 JMethodCall call; 558 JClassType javaLangString = program.getTypeJavaLangString(); 559 if (newType == javaLangString) { 560 566 int ctorArgc = ctor.params.size(); 567 JMethod targetMethod = null; 568 outer : for (int j = 0; j < javaLangString.methods.size(); ++j) { 569 JMethod method = (JMethod) javaLangString.methods.get(j); 570 if (method.getName().equals("_String") 571 && method.params.size() == ctorArgc) { 572 for (int i = 0; i < ctorArgc; ++i) { 573 JParameter mparam = (JParameter) method.params.get(i); 574 JParameter cparam = (JParameter) ctor.params.get(i); 575 if (mparam.getType() != cparam.getType()) { 576 continue outer; 577 } 578 } 579 targetMethod = method; 580 break; 581 } 582 } 583 if (targetMethod == null) { 584 throw new InternalCompilerException( 585 "String constructor error; no matching implementation."); 586 } 587 call = new JMethodCall(program, makeSourceInfo(x), null, targetMethod); 588 } else { 589 JNewInstance newInstance = new JNewInstance(program, info, newType); 590 call = new JMethodCall(program, info, newInstance, ctor); 591 } 592 593 if (x.arguments != null) { 595 for (int i = 0, n = x.arguments.length; i < n; ++i) { 596 call.getArgs().add(dispProcessExpression(x.arguments[i])); 597 } 598 } 599 600 ReferenceBinding targetBinding = b.declaringClass; 602 if (targetBinding.isNestedType() && !targetBinding.isStatic()) { 603 NestedTypeBinding nestedBinding = (NestedTypeBinding) targetBinding; 604 if (nestedBinding.enclosingInstances != null) { 606 for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) { 607 SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i]; 608 JClassType syntheticThisType = (JClassType) typeMap.get(arg.type); 609 call.getArgs().add(createThisRef(info, syntheticThisType)); 610 } 611 } 612 if (nestedBinding.outerLocalVariables != null) { 614 for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) { 615 SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i]; 616 JVariable variable = (JVariable) typeMap.get(arg.actualOuterLocalVariable); 617 call.getArgs().add( 618 createVariableRef(info, variable, arg.actualOuterLocalVariable)); 619 } 620 } 621 } 622 623 return call; 624 } 625 626 JExpression processExpression(AND_AND_Expression x) { 627 JType type = (JType) typeMap.get(x.resolvedType); 628 SourceInfo info = makeSourceInfo(x); 629 return processBinaryOperation(info, JBinaryOperator.AND, type, x.left, 630 x.right); 631 } 632 633 JExpression processExpression(ArrayAllocationExpression x) { 634 SourceInfo info = makeSourceInfo(x); 635 JArrayType type = (JArrayType) typeMap.get(x.resolvedType); 636 JNewArray newArray = new JNewArray(program, info, type); 637 638 if (x.initializer != null) { 639 newArray.initializers = new ArrayList (); 640 if (x.initializer.expressions != null) { 641 for (int i = 0; i < x.initializer.expressions.length; i++) { 642 Expression expression = x.initializer.expressions[i]; 643 newArray.initializers.add(dispProcessExpression(expression)); 644 } 645 } 646 } else { 647 newArray.dims = new ArrayList (); 648 for (int i = 0; i < x.dimensions.length; i++) { 649 Expression dimension = x.dimensions[i]; 650 if (dimension == null) { 652 newArray.dims.add(program.getLiteralAbsentArrayDimension()); 653 } else { 654 newArray.dims.add(dispProcessExpression(dimension)); 655 } 656 } 657 } 658 659 return newArray; 660 } 661 662 JExpression processExpression(ArrayInitializer x) { 663 SourceInfo info = makeSourceInfo(x); 664 JArrayType type = (JArrayType) typeMap.get(x.resolvedType); 665 JNewArray newArray = new JNewArray(program, info, type); 666 667 newArray.initializers = new ArrayList (); 668 if (x.expressions != null) { 669 for (int i = 0; i < x.expressions.length; i++) { 670 Expression expression = x.expressions[i]; 671 newArray.initializers.add(dispProcessExpression(expression)); 672 } 673 } 674 675 return newArray; 676 } 677 678 JExpression processExpression(ArrayReference x) { 679 SourceInfo info = makeSourceInfo(x); 680 JArrayRef arrayRef = new JArrayRef(program, info, 681 dispProcessExpression(x.receiver), dispProcessExpression(x.position)); 682 return arrayRef; 683 } 684 685 JExpression processExpression(Assignment x) { 686 JType type = (JType) typeMap.get(x.resolvedType); 687 SourceInfo info = makeSourceInfo(x); 688 return processBinaryOperation(info, JBinaryOperator.ASG, type, x.lhs, 689 x.expression); 690 } 691 692 JExpression processExpression(BinaryExpression x) { 693 JBinaryOperator op; 694 695 int binOp = (x.bits & BinaryExpression.OperatorMASK) >> BinaryExpression.OperatorSHIFT; 696 switch (binOp) { 697 case BinaryExpression.LEFT_SHIFT: 698 op = JBinaryOperator.SHL; 699 break; 700 case BinaryExpression.RIGHT_SHIFT: 701 op = JBinaryOperator.SHR; 702 break; 703 case BinaryExpression.UNSIGNED_RIGHT_SHIFT: 704 op = JBinaryOperator.SHRU; 705 break; 706 case BinaryExpression.PLUS: 707 op = JBinaryOperator.ADD; 708 break; 709 case BinaryExpression.MINUS: 710 op = JBinaryOperator.SUB; 711 break; 712 case BinaryExpression.REMAINDER: 713 op = JBinaryOperator.MOD; 714 break; 715 case BinaryExpression.XOR: 716 op = JBinaryOperator.BIT_XOR; 717 break; 718 case BinaryExpression.AND: 719 op = JBinaryOperator.BIT_AND; 720 break; 721 case BinaryExpression.MULTIPLY: 722 op = JBinaryOperator.MUL; 723 break; 724 case BinaryExpression.OR: 725 op = JBinaryOperator.BIT_OR; 726 break; 727 case BinaryExpression.DIVIDE: 728 op = JBinaryOperator.DIV; 729 break; 730 case BinaryExpression.LESS_EQUAL: 731 op = JBinaryOperator.LTE; 732 break; 733 case BinaryExpression.GREATER_EQUAL: 734 op = JBinaryOperator.GTE; 735 break; 736 case BinaryExpression.GREATER: 737 op = JBinaryOperator.GT; 738 break; 739 case BinaryExpression.LESS: 740 op = JBinaryOperator.LT; 741 break; 742 default: 743 throw new InternalCompilerException( 744 "Unexpected operator for BinaryExpression"); 745 } 746 747 JType type = (JType) typeMap.get(x.resolvedType); 748 SourceInfo info = makeSourceInfo(x); 749 return processBinaryOperation(info, op, type, x.left, x.right); 750 } 751 752 JExpression processExpression(CastExpression x) { 753 SourceInfo info = makeSourceInfo(x); 754 JType type = (JType) typeMap.get(x.resolvedType); 755 JCastOperation cast = new JCastOperation(program, info, type, 756 dispProcessExpression(x.expression)); 757 return cast; 758 } 759 760 JExpression processExpression(ClassLiteralAccess x) { 761 JType type = (JType) typeMap.get(x.targetType); 762 return program.getLiteralClass(type); 763 } 764 765 JExpression processExpression(CompoundAssignment x) { 766 JBinaryOperator op; 767 768 switch (x.operator) { 769 case CompoundAssignment.PLUS: 770 op = JBinaryOperator.ASG_ADD; 771 break; 772 case CompoundAssignment.MINUS: 773 op = JBinaryOperator.ASG_SUB; 774 break; 775 case CompoundAssignment.MULTIPLY: 776 op = JBinaryOperator.ASG_MUL; 777 break; 778 case CompoundAssignment.DIVIDE: 779 op = JBinaryOperator.ASG_DIV; 780 break; 781 case CompoundAssignment.AND: 782 op = JBinaryOperator.ASG_BIT_AND; 783 break; 784 case CompoundAssignment.OR: 785 op = JBinaryOperator.ASG_BIT_OR; 786 break; 787 case CompoundAssignment.XOR: 788 op = JBinaryOperator.ASG_BIT_XOR; 789 break; 790 case CompoundAssignment.REMAINDER: 791 op = JBinaryOperator.ASG_MOD; 792 break; 793 case CompoundAssignment.LEFT_SHIFT: 794 op = JBinaryOperator.ASG_SHL; 795 break; 796 case CompoundAssignment.RIGHT_SHIFT: 797 op = JBinaryOperator.ASG_SHR; 798 break; 799 case CompoundAssignment.UNSIGNED_RIGHT_SHIFT: 800 op = JBinaryOperator.ASG_SHRU; 801 break; 802 default: 803 throw new InternalCompilerException( 804 "Unexpected operator for CompoundAssignment"); 805 } 806 807 JType type = (JType) typeMap.get(x.resolvedType); 808 SourceInfo info = makeSourceInfo(x); 809 return processBinaryOperation(info, op, type, x.lhs, x.expression); 810 } 811 812 JExpression processExpression(ConditionalExpression x) { 813 SourceInfo info = makeSourceInfo(x); 814 JType type = (JType) typeMap.get(x.resolvedType); 815 JExpression ifTest = dispProcessExpression(x.condition); 816 JExpression thenExpr = dispProcessExpression(x.valueIfTrue); 817 JExpression elseExpr = dispProcessExpression(x.valueIfFalse); 818 JConditional conditional = new JConditional(program, info, type, ifTest, 819 thenExpr, elseExpr); 820 return conditional; 821 } 822 823 JExpression processExpression(EqualExpression x) { 824 JBinaryOperator op; 825 switch ((x.bits & BinaryExpression.OperatorMASK) >> BinaryExpression.OperatorSHIFT) { 826 case BinaryExpression.EQUAL_EQUAL: 827 op = JBinaryOperator.EQ; 828 break; 829 case BinaryExpression.NOT_EQUAL: 830 op = JBinaryOperator.NEQ; 831 break; 832 default: 833 throw new InternalCompilerException( 834 "Unexpected operator for EqualExpression"); 835 } 836 837 JType type = (JType) typeMap.get(x.resolvedType); 838 SourceInfo info = makeSourceInfo(x); 839 return processBinaryOperation(info, op, type, x.left, x.right); 840 } 841 842 846 JMethodCall processExpression(ExplicitConstructorCall x) { 847 if (x.isSuperAccess()) { 848 return processSuperConstructorCall(x); 849 } else { 850 return processThisConstructorCall(x); 851 } 852 } 853 854 JExpression processExpression(FieldReference x) { 855 SourceInfo info = makeSourceInfo(x); 856 FieldBinding fieldBinding = x.binding; 857 JField field; 858 if (fieldBinding.declaringClass == null) { 859 field = program.getSpecialField("Array.length"); 861 if (!field.getName().equals(String.valueOf(fieldBinding.name))) { 862 throw new InternalCompilerException("Error matching fieldBinding."); 863 } 864 } else { 865 field = (JField) typeMap.get(fieldBinding); 866 } 867 JExpression instance = dispProcessExpression(x.receiver); 868 JExpression fieldRef = new JFieldRef(program, info, instance, field, 869 currentClass); 870 return fieldRef; 871 } 872 873 JExpression processExpression(InstanceOfExpression x) { 874 SourceInfo info = makeSourceInfo(x); 875 JExpression expr = dispProcessExpression(x.expression); 876 JReferenceType testType = (JReferenceType) typeMap.get(x.type.resolvedType); 877 return new JInstanceOf(program, info, testType, expr); 878 } 879 880 JExpression processExpression(MessageSend x) { 881 SourceInfo info = makeSourceInfo(x); 882 JType type = (JType) typeMap.get(x.resolvedType); 883 JMethod method = (JMethod) typeMap.get(x.binding); 884 assert (type == method.getType()); 885 886 JExpression qualifier; 887 if (x.receiver instanceof ThisReference) { 888 if (method.isStatic()) { 889 qualifier = null; 891 } else if (x.receiver instanceof QualifiedThisReference) { 892 qualifier = dispProcessExpression(x.receiver); 894 } else { 895 900 qualifier = createThisRef(info, method.getEnclosingType()); 901 } 902 } else { 903 qualifier = dispProcessExpression(x.receiver); 904 } 905 906 JMethodCall call = new JMethodCall(program, info, qualifier, method); 907 908 boolean isSuperRef = x.receiver instanceof SuperReference 911 || x.receiver instanceof QualifiedSuperReference; 912 if (isSuperRef) { 913 call.setStaticDispatchOnly(); 914 } 915 916 if (x.arguments != null) { 918 for (int i = 0, n = x.arguments.length; i < n; ++i) { 919 call.getArgs().add(dispProcessExpression(x.arguments[i])); 920 } 921 } 922 923 return call; 924 } 925 926 JExpression processExpression(NullLiteral x) { 927 return program.getLiteralNull(); 928 } 929 930 JExpression processExpression(OR_OR_Expression x) { 931 JType type = (JType) typeMap.get(x.resolvedType); 932 SourceInfo info = makeSourceInfo(x); 933 return processBinaryOperation(info, JBinaryOperator.OR, type, x.left, 934 x.right); 935 } 936 937 JExpression processExpression(PostfixExpression x) { 938 SourceInfo info = makeSourceInfo(x); 939 JUnaryOperator op; 940 941 switch (x.operator) { 942 case PostfixExpression.MINUS: 943 op = JUnaryOperator.DEC; 944 break; 945 946 case PostfixExpression.PLUS: 947 op = JUnaryOperator.INC; 948 break; 949 950 default: 951 throw new InternalCompilerException("Unexpected postfix operator"); 952 } 953 954 JPostfixOperation postOp = new JPostfixOperation(program, info, op, 955 dispProcessExpression(x.lhs)); 956 return postOp; 957 } 958 959 JExpression processExpression(PrefixExpression x) { 960 SourceInfo info = makeSourceInfo(x); 961 JUnaryOperator op; 962 963 switch (x.operator) { 964 case PrefixExpression.MINUS: 965 op = JUnaryOperator.DEC; 966 break; 967 968 case PrefixExpression.PLUS: 969 op = JUnaryOperator.INC; 970 break; 971 972 default: 973 throw new InternalCompilerException("Unexpected prefix operator"); 974 } 975 976 JPrefixOperation preOp = new JPrefixOperation(program, info, op, 977 dispProcessExpression(x.lhs)); 978 return preOp; 979 } 980 981 JExpression processExpression(QualifiedAllocationExpression x) { 982 991 if (x.enclosingInstance() == null) { 992 return processExpression((AllocationExpression) x); 993 } 994 995 SourceInfo info = makeSourceInfo(x); 996 MethodBinding b = x.binding; 997 JMethod ctor = (JMethod) typeMap.get(b); 998 JClassType enclosingType = (JClassType) ctor.getEnclosingType(); 999 JNewInstance newInstance = new JNewInstance(program, info, enclosingType); 1000 JMethodCall call = new JMethodCall(program, info, newInstance, ctor); 1001 JExpression qualifier = dispProcessExpression(x.enclosingInstance); 1002 List qualList = new ArrayList (); 1003 qualList.add(qualifier); 1004 1005 1010 if (!currentMethod.isStatic()) { 1011 JExpression implicitOuter = program.getExprThisRef(info, 1012 (JClassType) currentClass); 1013 qualList.add(implicitOuter); 1014 } 1015 1016 if (x.arguments != null) { 1018 for (int i = 0, n = x.arguments.length; i < n; ++i) { 1019 call.getArgs().add(dispProcessExpression(x.arguments[i])); 1020 } 1021 } 1022 1023 ReferenceBinding targetBinding = b.declaringClass; 1025 if (targetBinding.isNestedType() && !targetBinding.isStatic()) { 1026 NestedTypeBinding nestedBinding = (NestedTypeBinding) targetBinding; 1027 if (nestedBinding.enclosingInstances != null) { 1029 for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) { 1030 SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i]; 1031 JClassType syntheticThisType = (JClassType) typeMap.get(arg.type); 1032 call.getArgs().add(createThisRef(syntheticThisType, qualList)); 1033 } 1034 } 1035 if (nestedBinding.outerLocalVariables != null) { 1037 for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) { 1038 SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i]; 1039 JVariable variable = (JVariable) typeMap.get(arg.actualOuterLocalVariable); 1040 call.getArgs().add( 1041 createVariableRef(info, variable, arg.actualOuterLocalVariable)); 1042 } 1043 } 1044 } 1045 1046 return call; 1047 } 1048 1049 JExpression processExpression(QualifiedNameReference x) { 1050 SourceInfo info = makeSourceInfo(x); 1051 Binding binding = x.binding; 1052 JNode node = typeMap.get(binding); 1053 if (!(node instanceof JVariable)) { 1054 return null; 1055 } 1056 JVariable variable = (JVariable) node; 1057 1058 JExpression curRef = createVariableRef(info, variable, binding); 1059 1060 1065 if (x.otherBindings != null) { 1066 for (int i = 0; i < x.otherBindings.length; i++) { 1067 FieldBinding fieldBinding = x.otherBindings[i]; 1068 JField field; 1069 if (fieldBinding.declaringClass == null) { 1070 field = program.getSpecialField("Array.length"); 1072 if (!field.getName().equals(String.valueOf(fieldBinding.name))) { 1073 throw new InternalCompilerException( 1074 "Error matching fieldBinding."); 1075 } 1076 } else { 1077 field = (JField) typeMap.get(fieldBinding); 1078 } 1079 curRef = new JFieldRef(program, info, curRef, field, currentClass); 1080 } 1081 } 1082 1083 return curRef; 1084 } 1085 1086 JExpression processExpression(QualifiedSuperReference x) { 1087 JClassType refType = (JClassType) typeMap.get(x.resolvedType); 1088 JClassType qualType = (JClassType) typeMap.get(x.qualification.resolvedType); 1089 assert (refType == qualType.extnds); 1090 return processQualifiedThisOrSuperRef(x, qualType); 1093 } 1094 1095 JExpression processExpression(QualifiedThisReference x) { 1096 JClassType refType = (JClassType) typeMap.get(x.resolvedType); 1097 JClassType qualType = (JClassType) typeMap.get(x.qualification.resolvedType); 1098 assert (refType == qualType); 1099 return processQualifiedThisOrSuperRef(x, qualType); 1100 } 1101 1102 JExpression processExpression(SingleNameReference x) { 1103 SourceInfo info = makeSourceInfo(x); 1104 Binding binding = x.binding; 1105 Object target = typeMap.get(binding); 1106 if (!(target instanceof JVariable)) { 1107 return null; 1108 } 1109 JVariable variable = (JVariable) target; 1110 1111 1117 if (x.syntheticAccessors != null) { 1118 JField field = (JField) variable; 1119 if (!field.isStatic()) { 1120 JExpression instance = createThisRef(info, field.getEnclosingType()); 1121 return new JFieldRef(program, info, instance, field, currentClass); 1122 } 1123 } 1124 1125 return createVariableRef(info, variable, binding); 1126 } 1127 1128 JExpression processExpression(SuperReference x) { 1129 JClassType type = (JClassType) typeMap.get(x.resolvedType); 1130 assert (type == currentClass.extnds); 1131 SourceInfo info = makeSourceInfo(x); 1132 JExpression superRef = createThisRef(info, currentClass); 1134 return superRef; 1135 } 1136 1137 JExpression processExpression(ThisReference x) { 1138 JClassType type = (JClassType) typeMap.get(x.resolvedType); 1139 assert (type == currentClass); 1140 SourceInfo info = makeSourceInfo(x); 1141 JExpression thisRef = createThisRef(info, currentClass); 1142 return thisRef; 1143 } 1144 1145 JExpression processExpression(UnaryExpression x) { 1146 SourceInfo info = makeSourceInfo(x); 1147 JUnaryOperator op; 1148 int operator = ((x.bits & UnaryExpression.OperatorMASK) >> UnaryExpression.OperatorSHIFT); 1149 1150 switch (operator) { 1151 case UnaryExpression.MINUS: 1152 op = JUnaryOperator.NEG; 1153 break; 1154 1155 case UnaryExpression.NOT: 1156 op = JUnaryOperator.NOT; 1157 break; 1158 1159 case UnaryExpression.PLUS: 1160 return dispProcessExpression(x.expression); 1162 1163 case UnaryExpression.TWIDDLE: 1164 op = JUnaryOperator.BIT_NOT; 1165 break; 1166 1167 default: 1168 throw new InternalCompilerException( 1169 "Unexpected operator for unary expression"); 1170 } 1171 1172 JPrefixOperation preOp = new JPrefixOperation(program, info, op, 1173 dispProcessExpression(x.expression)); 1174 return preOp; 1175 } 1176 1177 void processField(FieldDeclaration declaration) { 1178 JField field = (JField) typeMap.tryGet(declaration.binding); 1179 if (field == null) { 1180 1185 return; 1186 } 1187 try { 1188 JExpression initializer = null; 1189 if (declaration.initialization != null) { 1190 initializer = dispProcessExpression(declaration.initialization); 1191 } 1192 1193 if (initializer instanceof JLiteral) { 1194 field.constInitializer = (JLiteral) initializer; 1195 } else if (initializer != null) { 1196 SourceInfo info = makeSourceInfo(declaration); 1197 JStatement assignStmt = program.createAssignmentStmt(info, 1198 createVariableRef(info, field), initializer); 1199 1200 currentMethod.body.statements.add(assignStmt); 1202 } 1203 } catch (Throwable e) { 1204 throw translateException(field, e); 1205 } 1206 } 1207 1208 void processInitializer(Initializer initializer) { 1209 JBlock block = (JBlock) dispProcessStatement(initializer.block); 1210 try { 1211 currentMethod.body.statements.add(block); 1213 } catch (Throwable e) { 1214 throw translateException(initializer, e); 1215 } 1216 } 1217 1218 void processMethod(AbstractMethodDeclaration x) { 1219 MethodBinding b = x.binding; 1220 JMethod method = (JMethod) typeMap.get(b); 1221 try { 1222 if (b.isImplementing() || b.isOverriding()) { 1223 tryFindUpRefs(method, b); 1224 } 1225 1226 if (x.isNative()) { 1227 processNativeMethod(x, (JsniMethod) method); 1228 return; 1229 } 1230 1231 currentMethod = method; 1232 currentMethodScope = x.scope; 1233 1234 if (x.statements != null) { 1235 for (int i = 0, n = x.statements.length; i < n; ++i) { 1236 Statement origStmt = x.statements[i]; 1237 JStatement jstmt = dispProcessStatement(origStmt); 1238 if (jstmt != null) { 1239 method.body.statements.add(jstmt); 1240 } 1241 } 1242 } 1243 currentMethodScope = null; 1244 currentMethod = null; 1245 } catch (Throwable e) { 1246 throw translateException(method, e); 1247 } 1248 } 1249 1250 void processNativeMethod(AbstractMethodDeclaration x, 1251 JsniMethod nativeMethod) { 1252 1253 JsFunction func = nativeMethod.getFunc(); 1254 if (func == null) { 1255 return; 1256 } 1257 1258 final List nameRefs = new ArrayList (); 1260 new JsVisitor() { 1261 public void endVisit(JsNameRef x, JsContext ctx) { 1263 String ident = x.getIdent(); 1264 if (ident.charAt(0) == '@') { 1265 nameRefs.add(x); 1266 } 1267 } 1268 }.accept(func); 1269 1270 for (int i = 0; i < nameRefs.size(); ++i) { 1271 JsNameRef nameRef = (JsNameRef) nameRefs.get(i); 1272 SourceInfo info = nativeMethod.getSourceInfo(); 1273 String ident = nameRef.getIdent(); 1276 HasEnclosingType node = (HasEnclosingType) program.jsniMap.get(ident); 1277 if (node == null) { 1278 node = parseJsniRef(info, x, ident); 1279 if (node == null) { 1280 continue; } 1282 program.jsniMap.put(ident, node); 1283 } 1284 assert (node != null); 1285 CanBeStatic canBeStatic = (CanBeStatic) node; 1286 HasName hasName = (HasName) node; 1287 boolean isField = node instanceof JField; 1288 assert (isField || node instanceof JMethod); 1289 if (canBeStatic.isStatic() && nameRef.getQualifier() != null) { 1290 reportJsniError(info, x, 1291 "Cannot make a qualified reference to the static " 1292 + (isField ? "field " : "method ") + hasName.getName()); 1293 } else if (!canBeStatic.isStatic() && nameRef.getQualifier() == null) { 1294 reportJsniError(info, x, 1295 "Cannot make an unqualified reference to the instance " 1296 + (isField ? "field " : "method ") + hasName.getName()); 1297 } 1298 1299 if (isField) { 1300 1304 JField field = (JField) node; 1305 JsniFieldRef fieldRef = new JsniFieldRef(program, info, field, 1306 currentClass); 1307 nativeMethod.jsniFieldRefs.add(fieldRef); 1308 } else { 1309 JMethod method = (JMethod) node; 1310 JsniMethodRef methodRef = new JsniMethodRef(program, info, method); 1311 nativeMethod.jsniMethodRefs.add(methodRef); 1312 } 1313 } 1314 } 1315 1316 JStatement processStatement(AssertStatement x) { 1317 SourceInfo info = makeSourceInfo(x); 1318 JExpression expr = dispProcessExpression(x.assertExpression); 1319 JExpression arg = dispProcessExpression(x.exceptionArgument); 1320 return new JAssertStatement(program, info, expr, arg); 1321 } 1322 1323 1328 JBlock processStatement(Block x) { 1329 if (x == null) { 1330 return null; 1331 } 1332 1333 SourceInfo info = makeSourceInfo(x); 1334 JBlock block = new JBlock(program, info); 1335 if (x.statements != null) { 1336 for (int i = 0, n = x.statements.length; i < n; ++i) { 1337 JStatement jstmt = dispProcessStatement(x.statements[i]); 1338 if (jstmt != null) { 1339 block.statements.add(jstmt); 1340 } 1341 } 1342 } 1343 return block; 1344 } 1345 1346 JStatement processStatement(BreakStatement x) { 1347 SourceInfo info = makeSourceInfo(x); 1348 return new JBreakStatement(program, info, getOrCreateLabel(info, 1349 currentMethod, x.label)); 1350 } 1351 1352 JStatement processStatement(CaseStatement x) { 1353 SourceInfo info = makeSourceInfo(x); 1354 JExpression expression = dispProcessExpression(x.constantExpression); 1355 return new JCaseStatement(program, info, (JLiteral) expression); 1356 } 1357 1358 JStatement processStatement(ContinueStatement x) { 1359 SourceInfo info = makeSourceInfo(x); 1360 return new JContinueStatement(program, info, getOrCreateLabel(info, 1361 currentMethod, x.label)); 1362 } 1363 1364 JStatement processStatement(DoStatement x) { 1365 SourceInfo info = makeSourceInfo(x); 1366 JExpression loopTest = dispProcessExpression(x.condition); 1367 JStatement loopBody = dispProcessStatement(x.action); 1368 JDoStatement stmt = new JDoStatement(program, info, loopTest, loopBody); 1369 return stmt; 1370 } 1371 1372 JStatement processStatement(EmptyStatement x) { 1373 return null; 1374 } 1375 1376 JStatement processStatement(ForStatement x) { 1377 SourceInfo info = makeSourceInfo(x); 1378 boolean removeBody = isOptimizedFalse(x.condition); 1381 1382 List init = processStatements(x.initializations); 1383 JExpression expr = dispProcessExpression(x.condition); 1384 List incr = processStatements(x.increments); 1385 JStatement body = removeBody ? null : dispProcessStatement(x.action); 1386 return new JForStatement(program, info, init, expr, incr, body); 1387 } 1388 1389 JStatement processStatement(IfStatement x) { 1390 boolean removeThen = isOptimizedFalse(x.condition); 1394 boolean removeElse = isOptimizedTrue(x.condition); 1395 1396 SourceInfo info = makeSourceInfo(x); 1397 JExpression expr = dispProcessExpression(x.condition); 1398 JStatement thenStmt = removeThen ? null 1399 : dispProcessStatement(x.thenStatement); 1400 JStatement elseStmt = removeElse ? null 1401 : dispProcessStatement(x.elseStatement); 1402 JIfStatement ifStmt = new JIfStatement(program, info, expr, thenStmt, 1403 elseStmt); 1404 return ifStmt; 1405 } 1406 1407 JStatement processStatement(LabeledStatement x) { 1408 JStatement body = dispProcessStatement(x.statement); 1409 if (body == null) { 1410 return null; 1411 } 1412 SourceInfo info = makeSourceInfo(x); 1413 return new JLabeledStatement(program, info, getOrCreateLabel(info, 1414 currentMethod, x.label), body); 1415 } 1416 1417 JStatement processStatement(LocalDeclaration x) { 1418 SourceInfo info = makeSourceInfo(x); 1419 JLocal local = (JLocal) typeMap.get(x.binding); 1420 JLocalRef localRef = new JLocalRef(program, info, local); 1421 JExpression initializer = dispProcessExpression(x.initialization); 1422 return new JLocalDeclarationStatement(program, info, localRef, 1423 initializer); 1424 } 1425 1426 JStatement processStatement(ReturnStatement x) { 1427 SourceInfo info = makeSourceInfo(x); 1428 if (currentMethodScope.referenceContext instanceof ConstructorDeclaration) { 1429 1434 JClassType enclosingType = (JClassType) currentMethod.getEnclosingType(); 1435 assert (x.expression == null); 1436 return new JReturnStatement(program, info, createThisRef(info, 1437 enclosingType)); 1438 } else { 1439 return new JReturnStatement(program, info, 1440 dispProcessExpression(x.expression)); 1441 } 1442 } 1443 1444 JStatement processStatement(SwitchStatement x) { 1445 SourceInfo info = makeSourceInfo(x); 1446 JExpression expression = dispProcessExpression(x.expression); 1447 JBlock block = new JBlock(program, info); 1448 block.statements = processStatements(x.statements); 1449 return new JSwitchStatement(program, info, expression, block); 1450 } 1451 1452 JStatement processStatement(SynchronizedStatement x) { 1453 SourceInfo info = makeSourceInfo(x); 1454 JBlock block = (JBlock) dispProcessStatement(x.block); 1455 JExpression expr = dispProcessExpression(x.expression); 1456 block.statements.add(0, expr.makeStatement()); 1457 return block; 1458 } 1459 1460 JStatement processStatement(ThrowStatement x) { 1461 SourceInfo info = makeSourceInfo(x); 1462 JExpression toThrow = dispProcessExpression(x.exception); 1463 return new JThrowStatement(program, info, toThrow); 1464 } 1465 1466 JStatement processStatement(TryStatement x) { 1467 SourceInfo info = makeSourceInfo(x); 1468 JBlock tryBlock = (JBlock) dispProcessStatement(x.tryBlock); 1469 List catchArgs = new ArrayList (); 1470 List catchBlocks = new ArrayList (); 1471 if (x.catchBlocks != null) { 1472 for (int i = 0, c = x.catchArguments.length; i < c; ++i) { 1473 JLocal local = (JLocal) typeMap.get(x.catchArguments[i].binding); 1474 catchArgs.add(createVariableRef(info, local)); 1475 } 1476 for (int i = 0, c = x.catchBlocks.length; i < c; ++i) { 1477 catchBlocks.add(dispProcessStatement(x.catchBlocks[i])); 1478 } 1479 } 1480 JBlock finallyBlock = (JBlock) dispProcessStatement(x.finallyBlock); 1481 return new JTryStatement(program, info, tryBlock, catchArgs, catchBlocks, 1482 finallyBlock); 1483 } 1484 1485 JStatement processStatement(TypeDeclaration x) { 1486 return null; 1488 } 1489 1490 JStatement processStatement(WhileStatement x) { 1491 boolean removeBody = isOptimizedFalse(x.condition); 1494 1495 SourceInfo info = makeSourceInfo(x); 1496 JExpression loopTest = dispProcessExpression(x.condition); 1497 JStatement loopBody = removeBody ? null : dispProcessStatement(x.action); 1498 JWhileStatement stmt = new JWhileStatement(program, info, loopTest, 1499 loopBody); 1500 return stmt; 1501 } 1502 1503 List processStatements(Statement[] statements) { 1504 List jstatements = new ArrayList (); 1505 if (statements != null) { 1506 for (int i = 0, n = statements.length; i < n; ++i) { 1507 JStatement jstmt = dispProcessStatement(statements[i]); 1508 if (jstmt != null) { 1509 jstatements.add(jstmt); 1510 } 1511 } 1512 } 1513 return jstatements; 1514 } 1515 1516 JMethodCall processSuperConstructorCall(ExplicitConstructorCall x) { 1517 SourceInfo info = makeSourceInfo(x); 1518 JMethod ctor = (JMethod) typeMap.get(x.binding); 1519 JExpression trueQualifier = createThisRef(info, currentClass); 1520 JMethodCall call = new JMethodCall(program, info, trueQualifier, ctor); 1521 1522 if (x.arguments != null) { 1523 for (int i = 0, n = x.arguments.length; i < n; ++i) { 1524 call.getArgs().add(dispProcessExpression(x.arguments[i])); 1525 } 1526 } 1527 1528 ReferenceBinding superClass = x.binding.declaringClass; 1530 if (superClass instanceof NestedTypeBinding && !superClass.isStatic()) { 1531 NestedTypeBinding myBinding = (NestedTypeBinding) currentClassScope.referenceType().binding; 1532 NestedTypeBinding superBinding = (NestedTypeBinding) superClass; 1533 1534 if (superBinding.enclosingInstances != null) { 1536 JExpression qualifier = dispProcessExpression(x.qualification); 1537 for (int j = 0; j < superBinding.enclosingInstances.length; ++j) { 1538 SyntheticArgumentBinding arg = superBinding.enclosingInstances[j]; 1539 JClassType classType = (JClassType) typeMap.get(arg.type); 1540 if (qualifier == null) { 1541 1549 List workList = new ArrayList (); 1550 Iterator paramIt = getSyntheticsIterator(currentMethod); 1551 for (int i = 0; i < myBinding.enclosingInstances.length; ++i) { 1552 workList.add(createVariableRef(info, 1553 (JParameter) paramIt.next())); 1554 } 1555 call.getArgs().add(createThisRef(classType, workList)); 1556 } else { 1557 call.getArgs().add(createThisRef(classType, qualifier)); 1558 } 1559 } 1560 } 1561 1562 if (superBinding.outerLocalVariables != null) { 1564 for (int j = 0; j < superBinding.outerLocalVariables.length; ++j) { 1565 SyntheticArgumentBinding arg = superBinding.outerLocalVariables[j]; 1566 JType varType = (JType) typeMap.get(arg.type); 1568 String varName = String.valueOf(arg.name); 1569 JParameter param = null; 1570 for (int i = 0; i < currentMethod.params.size(); ++i) { 1571 JParameter paramIt = (JParameter) currentMethod.params.get(i); 1572 if (varType == paramIt.getType() 1573 && varName.equals(paramIt.getName())) { 1574 param = paramIt; 1575 } 1576 } 1577 if (param == null) { 1578 throw new InternalCompilerException( 1579 "Could not find matching local arg for explicit super ctor call."); 1580 } 1581 call.getArgs().add(createVariableRef(info, param)); 1582 } 1583 } 1584 } 1585 1586 return call; 1587 } 1588 1589 JMethodCall processThisConstructorCall(ExplicitConstructorCall x) { 1590 SourceInfo info = makeSourceInfo(x); 1591 JMethod ctor = (JMethod) typeMap.get(x.binding); 1592 JExpression trueQualifier = createThisRef(info, currentClass); 1593 JMethodCall call = new JMethodCall(program, info, trueQualifier, ctor); 1594 1595 assert (x.qualification == null); 1596 1597 if (x.arguments != null) { 1598 for (int i = 0, n = x.arguments.length; i < n; ++i) { 1599 call.getArgs().add(dispProcessExpression(x.arguments[i])); 1600 } 1601 } 1602 1603 ReferenceBinding declaringClass = x.binding.declaringClass; 1605 if (declaringClass instanceof NestedTypeBinding) { 1606 Iterator paramIt = getSyntheticsIterator(currentMethod); 1607 NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass; 1608 if (nestedBinding.enclosingInstances != null) { 1609 for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) { 1610 call.getArgs().add( 1611 createVariableRef(info, (JParameter) paramIt.next())); 1612 } 1613 } 1614 if (nestedBinding.outerLocalVariables != null) { 1615 for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) { 1616 call.getArgs().add( 1617 createVariableRef(info, (JParameter) paramIt.next())); 1618 } 1619 } 1620 } 1621 1622 return call; 1623 } 1624 1625 private void addAllOuterThisRefs(List list, JExpression expr, 1626 JClassType classType) { 1627 if (classType.fields.size() > 0) { 1628 JField field = (JField) classType.fields.get(0); 1629 if (field.getName().startsWith("this$")) { 1630 list.add(new JFieldRef(program, expr.getSourceInfo(), expr, field, 1631 currentClass)); 1632 } 1633 } 1634 } 1635 1636 private void addAllOuterThisRefsPlusSuperChain(List workList, 1637 JExpression expr, JClassType classType) { 1638 for (; classType != null; classType = classType.extnds) { 1639 addAllOuterThisRefs(workList, expr, classType); 1640 } 1641 } 1642 1643 private boolean areParametersIdentical(MethodBinding a, MethodBinding b) { 1644 TypeBinding[] params1 = a.parameters; 1645 TypeBinding[] params2 = b.parameters; 1646 if (params1.length != params2.length) { 1647 return false; 1648 } 1649 1650 for (int i = 0; i < params1.length; ++i) { 1651 if (params1[i] != params2[i]) { 1652 return false; 1653 } 1654 } 1655 1656 return true; 1657 } 1658 1659 1664 private JExpression createQualifiedThisRef(SourceInfo info, 1665 JClassType targetType) { 1666 assert (currentClass instanceof JClassType); 1667 JExpression expr = program.getExprThisRef(info, (JClassType) currentClass); 1668 List list = new ArrayList (); 1669 addAllOuterThisRefsPlusSuperChain(list, expr, (JClassType) currentClass); 1670 return createThisRef(targetType, list); 1671 } 1672 1673 1679 private JExpression createThisRef(JReferenceType qualType, JExpression expr) { 1680 List list = new ArrayList (); 1681 list.add(expr); 1682 return createThisRef(qualType, list); 1683 } 1684 1685 1704 private JExpression createThisRef(JReferenceType qualType, 1705 List list) { 1706 LinkedList workList = new LinkedList (); 1707 workList.addAll(list); 1708 while (!workList.isEmpty()) { 1709 JExpression expr = (JExpression) workList.removeFirst(); 1710 JClassType classType = (JClassType) expr.getType(); 1711 for (; classType != null; classType = classType.extnds) { 1712 if (program.typeOracle.canTriviallyCast(classType, qualType)) { 1715 return expr; 1716 } 1717 addAllOuterThisRefs(workList, expr, classType); 1718 } 1719 } 1720 1721 throw new InternalCompilerException( 1722 "Cannot create a ThisRef of the appropriate type."); 1723 } 1724 1725 1730 private JExpression createThisRef(SourceInfo info, JReferenceType targetType) { 1731 assert (currentClass instanceof JClassType); 1732 return createThisRef(targetType, program.getExprThisRef(info, 1733 (JClassType) currentClass)); 1734 } 1735 1736 1740 private JVariableRef createVariableRef(SourceInfo info, JVariable variable) { 1741 if (variable instanceof JLocal) { 1742 JLocal local = (JLocal) variable; 1743 if (local.getEnclosingMethod() != currentMethod) { 1744 throw new InternalCompilerException( 1745 "LocalRef referencing local in a different method."); 1746 } 1747 return new JLocalRef(program, info, local); 1748 } else if (variable instanceof JParameter) { 1749 JParameter parameter = (JParameter) variable; 1750 if (parameter.getEnclosingMethod() != currentMethod) { 1751 throw new InternalCompilerException( 1752 "ParameterRef referencing param in a different method."); 1753 } 1754 return new JParameterRef(program, info, parameter); 1755 } else if (variable instanceof JField) { 1756 JField field = (JField) variable; 1757 JExpression instance = null; 1758 if (!field.isStatic()) { 1759 JClassType fieldEnclosingType = (JClassType) field.getEnclosingType(); 1760 instance = createThisRef(info, fieldEnclosingType); 1761 if (!program.typeOracle.canTriviallyCast( 1762 (JClassType) instance.getType(), fieldEnclosingType)) { 1763 throw new InternalCompilerException( 1764 "FieldRef referencing field in a different type."); 1765 } 1766 } 1767 return new JFieldRef(program, info, instance, field, currentClass); 1768 } 1769 throw new InternalCompilerException("Unknown JVariable subclass."); 1770 } 1771 1772 1776 private JVariableRef createVariableRef(SourceInfo info, JVariable variable, 1777 Binding binding) { 1778 variable = possiblyReferenceOuterLocal(variable, binding); 1780 if (variable == null) { 1781 1787 return null; 1788 } 1789 return createVariableRef(info, variable); 1790 } 1791 1792 1796 private JLabel getOrCreateLabel(SourceInfo info, JMethod enclosingMethod, 1797 char[] name) { 1798 if (name == null) { 1799 return null; 1800 } 1801 String sname = String.valueOf(name); 1802 Map lblMap = (Map ) this.labelMap.get(enclosingMethod); 1803 if (lblMap == null) { 1804 lblMap = new HashMap (); 1805 this.labelMap.put(enclosingMethod, lblMap); 1806 } 1807 JLabel jlabel = (JLabel) lblMap.get(sname); 1808 if (jlabel == null) { 1809 jlabel = new JLabel(program, info, sname); 1810 lblMap.put(sname, jlabel); 1811 } 1812 return jlabel; 1813 } 1814 1815 private SourceInfo makeSourceInfo(Statement x) { 1816 int startLine = ProblemHandler.searchLineNumber( 1817 currentSeparatorPositions, x.sourceStart); 1818 return new SourceInfo(x.sourceStart, x.sourceEnd, startLine, 1819 currentFileName); 1820 } 1821 1822 private HasEnclosingType parseJsniRef(SourceInfo info, 1823 AbstractMethodDeclaration x, String ident) { 1824 String [] parts = ident.substring(1).split("::"); 1825 assert (parts.length == 2); 1826 String className = parts[0]; 1827 JReferenceType type = program.getFromTypeMap(className); 1828 if (type == null) { 1829 reportJsniError(info, x, "Unresolvable native reference to type '" 1830 + className + "'"); 1831 return null; 1832 } 1833 String rhs = parts[1]; 1834 int parenPos = rhs.indexOf('('); 1835 if (parenPos < 0) { 1836 for (int i = 0; i < type.fields.size(); ++i) { 1838 JField field = (JField) type.fields.get(i); 1839 if (field.getName().equals(rhs)) { 1840 return field; 1841 } 1842 } 1843 1844 reportJsniError(info, x, "Unresolvable native reference to field '" 1845 + rhs + "' in type '" + className + "'"); 1846 } else { 1847 String methodName = rhs.substring(0, parenPos); 1849 String almostMatches = null; 1850 for (int i = 0; i < type.methods.size(); ++i) { 1851 JMethod method = (JMethod) type.methods.get(i); 1852 if (method.getName().equals(methodName)) { 1853 String jsniSig = getJsniSig(method); 1854 if (jsniSig.equals(rhs)) { 1855 return method; 1856 } else if (almostMatches == null) { 1857 almostMatches = "'" + jsniSig + "'"; 1858 } else { 1859 almostMatches += ", '" + jsniSig + "'"; 1860 } 1861 } 1862 } 1863 1864 if (almostMatches == null) { 1865 reportJsniError(info, x, "Unresolvable native reference to method '" 1866 + methodName + "' in type '" + className + "'"); 1867 } else { 1868 reportJsniError(info, x, "Unresolvable native reference to method '" 1869 + methodName + "' in type '" + className + "' (did you mean " 1870 + almostMatches + "?)"); 1871 } 1872 } 1873 return null; 1874 } 1875 1876 1886 private JVariable possiblyReferenceOuterLocal(JVariable variable, 1887 Binding binding) { 1888 1889 if (variable instanceof JLocal || variable instanceof JParameter) { 1890 LocalVariableBinding localBinding = (LocalVariableBinding) binding; 1891 if (localBinding.declaringScope.methodScope() != currentMethodScope) { 1892 variable = null; 1893 VariableBinding[] vars = currentMethodScope.getEmulationPath(localBinding); 1894 if (vars == null) { 1895 return null; 1896 } 1897 assert (vars.length == 1); 1898 VariableBinding varBinding = vars[0]; 1899 1900 if (varBinding instanceof SyntheticArgumentBinding) { 1902 JType type = (JType) typeMap.get(varBinding.type); 1903 String name = String.valueOf(varBinding.name); 1904 for (int i = 0; i < currentMethod.params.size(); ++i) { 1905 JParameter param = (JParameter) currentMethod.params.get(i); 1906 if (type == param.getType() && name.equals(param.getName())) { 1907 variable = param; 1908 break; 1909 } 1910 } 1911 } 1912 1913 if (variable == null) { 1915 variable = (JField) typeMap.get(varBinding); 1916 } 1917 1918 } 1920 } 1921 return variable; 1922 } 1923 1924 1933 private JExpression processBinaryOperation(SourceInfo info, 1934 JBinaryOperator op, JType type, Expression arg1, Expression arg2) { 1935 JExpression exprArg1 = dispProcessExpression(arg1); 1936 JExpression exprArg2 = dispProcessExpression(arg2); 1937 JBinaryOperation binaryOperation = new JBinaryOperation(program, info, 1938 type, op, exprArg1, exprArg2); 1939 return binaryOperation; 1940 } 1941 1942 private JExpression processQualifiedThisOrSuperRef( 1943 QualifiedThisReference x, JClassType qualType) { 1944 1955 SourceInfo info = makeSourceInfo(x); 1956 if (qualType == currentClass) { 1957 return createThisRef(info, qualType); 1958 } else { 1959 return createQualifiedThisRef(info, qualType); 1960 } 1961 } 1962 1963 private InternalCompilerException translateException(Object node, 1964 Throwable e) { 1965 InternalCompilerException ice; 1966 if (e instanceof InternalCompilerException) { 1967 ice = (InternalCompilerException) e; 1968 } else { 1969 ice = new InternalCompilerException("Error constructing Java AST", e); 1970 } 1971 String className = node.getClass().getName(); 1972 String description = node.toString(); 1973 SourceInfo sourceInfo = null; 1974 if (node instanceof Statement) { 1975 sourceInfo = makeSourceInfo((Statement) node); 1976 } 1977 ice.addNode(className, description, sourceInfo); 1978 return ice; 1979 } 1980 1981 1985 private void tryFindUpRefs(JMethod method, MethodBinding binding) { 1986 tryFindUpRefsRecursive(method, binding, binding.declaringClass); 1987 } 1988 1989 1993 private void tryFindUpRefsRecursive(JMethod method, MethodBinding binding, 1994 ReferenceBinding searchThisType) { 1995 1996 if (binding.declaringClass != searchThisType) { 1998 MethodBinding result = searchThisType.getExactMethod(binding.selector, 1999 binding.parameters, null); 2000 2001 if (result != null) { 2002 if (areParametersIdentical(binding, result)) { 2003 JMethod upRef = (JMethod) typeMap.get(result); 2004 if (!method.overrides.contains(upRef)) { 2005 method.overrides.add(upRef); 2006 } 2007 } 2008 } 2009 } 2010 2011 if (searchThisType.superclass() != null) { 2013 tryFindUpRefsRecursive(method, binding, searchThisType.superclass()); 2014 } 2015 2016 if (searchThisType.superInterfaces() != null) { 2018 for (int i = 0; i < searchThisType.superInterfaces().length; i++) { 2019 ReferenceBinding intf = searchThisType.superInterfaces()[i]; 2020 tryFindUpRefsRecursive(method, binding, intf); 2021 } 2022 } 2023 } 2024 } 2025 2026 2030 public static void exec(TypeDeclaration[] types, TypeMap typeMap, 2031 JProgram jprogram) { 2032 JavaASTGenerationVisitor v = new JavaASTGenerationVisitor(typeMap); 2033 for (int i = 0; i < types.length; ++i) { 2034 v.processType(types[i]); 2035 } 2036 Collections.sort(jprogram.getDeclaredTypes(), new HasNameSort()); 2037 } 2038 2039 public static void reportJsniError(SourceInfo info, 2040 AbstractMethodDeclaration methodDeclaration, String message) { 2041 CompilationResult compResult = methodDeclaration.compilationResult(); 2042 DefaultProblem problem = new DefaultProblem( 2043 info.getFileName().toCharArray(), message, IProblem.Unclassified, null, 2044 ProblemSeverities.Error, info.getStartPos(), info.getEndPos(), 2045 info.getStartLine()); 2046 compResult.record(problem, methodDeclaration); 2047 } 2048 2049 public static SourceInfo translateInfo(JsSourceInfo info) { 2050 return null; 2052 } 2053 2054 2058 private static Iterator getSyntheticsIterator(JMethod method) { 2059 Iterator it = method.params.iterator(); 2060 for (int i = 0, c = method.getOriginalParamTypes().size(); i < c; ++i) { 2061 it.next(); 2062 } 2063 return it; 2064 } 2065 2066 2070 private static boolean isOptimizedFalse(Expression condition) { 2071 if (condition != null) { 2072 Constant cst = condition.optimizedBooleanConstant(); 2073 if (cst != Constant.NotAConstant) { 2074 if (cst.booleanValue() == false) { 2075 return true; 2076 } 2077 } 2078 } 2079 return false; 2080 } 2081 2082 2086 private static boolean isOptimizedTrue(Expression condition) { 2087 if (condition != null) { 2088 Constant cst = condition.optimizedBooleanConstant(); 2089 if (cst != Constant.NotAConstant) { 2090 if (cst.booleanValue() == true) { 2091 return true; 2092 } 2093 } 2094 } 2095 return false; 2096 } 2097 2098} 2099 | Popular Tags |