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.ast.Context; 20 import com.google.gwt.dev.jjs.ast.HasEnclosingType; 21 import com.google.gwt.dev.jjs.ast.HasName; 22 import com.google.gwt.dev.jjs.ast.JAbsentArrayDimension; 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.JClassLiteral; 35 import com.google.gwt.dev.jjs.ast.JClassType; 36 import com.google.gwt.dev.jjs.ast.JConditional; 37 import com.google.gwt.dev.jjs.ast.JContinueStatement; 38 import com.google.gwt.dev.jjs.ast.JDoStatement; 39 import com.google.gwt.dev.jjs.ast.JDoubleLiteral; 40 import com.google.gwt.dev.jjs.ast.JExpressionStatement; 41 import com.google.gwt.dev.jjs.ast.JField; 42 import com.google.gwt.dev.jjs.ast.JFieldRef; 43 import com.google.gwt.dev.jjs.ast.JFloatLiteral; 44 import com.google.gwt.dev.jjs.ast.JForStatement; 45 import com.google.gwt.dev.jjs.ast.JIfStatement; 46 import com.google.gwt.dev.jjs.ast.JInstanceOf; 47 import com.google.gwt.dev.jjs.ast.JIntLiteral; 48 import com.google.gwt.dev.jjs.ast.JInterfaceType; 49 import com.google.gwt.dev.jjs.ast.JLabel; 50 import com.google.gwt.dev.jjs.ast.JLabeledStatement; 51 import com.google.gwt.dev.jjs.ast.JLocal; 52 import com.google.gwt.dev.jjs.ast.JLocalDeclarationStatement; 53 import com.google.gwt.dev.jjs.ast.JLocalRef; 54 import com.google.gwt.dev.jjs.ast.JLongLiteral; 55 import com.google.gwt.dev.jjs.ast.JMethod; 56 import com.google.gwt.dev.jjs.ast.JMethodCall; 57 import com.google.gwt.dev.jjs.ast.JNewArray; 58 import com.google.gwt.dev.jjs.ast.JNewInstance; 59 import com.google.gwt.dev.jjs.ast.JNullLiteral; 60 import com.google.gwt.dev.jjs.ast.JParameter; 61 import com.google.gwt.dev.jjs.ast.JParameterRef; 62 import com.google.gwt.dev.jjs.ast.JPostfixOperation; 63 import com.google.gwt.dev.jjs.ast.JPrefixOperation; 64 import com.google.gwt.dev.jjs.ast.JProgram; 65 import com.google.gwt.dev.jjs.ast.JReferenceType; 66 import com.google.gwt.dev.jjs.ast.JReturnStatement; 67 import com.google.gwt.dev.jjs.ast.JStatement; 68 import com.google.gwt.dev.jjs.ast.JStringLiteral; 69 import com.google.gwt.dev.jjs.ast.JSwitchStatement; 70 import com.google.gwt.dev.jjs.ast.JThisRef; 71 import com.google.gwt.dev.jjs.ast.JThrowStatement; 72 import com.google.gwt.dev.jjs.ast.JTryStatement; 73 import com.google.gwt.dev.jjs.ast.JType; 74 import com.google.gwt.dev.jjs.ast.JTypeOracle; 75 import com.google.gwt.dev.jjs.ast.JUnaryOperator; 76 import com.google.gwt.dev.jjs.ast.JVisitor; 77 import com.google.gwt.dev.jjs.ast.JWhileStatement; 78 import com.google.gwt.dev.jjs.ast.js.JClassSeed; 79 import com.google.gwt.dev.jjs.ast.js.JMultiExpression; 80 import com.google.gwt.dev.jjs.ast.js.JsniMethod; 81 import com.google.gwt.dev.jjs.ast.js.JsonArray; 82 import com.google.gwt.dev.jjs.ast.js.JsonObject; 83 import com.google.gwt.dev.jjs.ast.js.JsonObject.JsonPropInit; 84 import com.google.gwt.dev.js.ast.JsArrayAccess; 85 import com.google.gwt.dev.js.ast.JsArrayLiteral; 86 import com.google.gwt.dev.js.ast.JsBinaryOperation; 87 import com.google.gwt.dev.js.ast.JsBinaryOperator; 88 import com.google.gwt.dev.js.ast.JsBlock; 89 import com.google.gwt.dev.js.ast.JsBreak; 90 import com.google.gwt.dev.js.ast.JsCase; 91 import com.google.gwt.dev.js.ast.JsCatch; 92 import com.google.gwt.dev.js.ast.JsCollection; 93 import com.google.gwt.dev.js.ast.JsConditional; 94 import com.google.gwt.dev.js.ast.JsContext; 95 import com.google.gwt.dev.js.ast.JsContinue; 96 import com.google.gwt.dev.js.ast.JsDefault; 97 import com.google.gwt.dev.js.ast.JsDoWhile; 98 import com.google.gwt.dev.js.ast.JsExprStmt; 99 import com.google.gwt.dev.js.ast.JsExpression; 100 import com.google.gwt.dev.js.ast.JsFor; 101 import com.google.gwt.dev.js.ast.JsFunction; 102 import com.google.gwt.dev.js.ast.JsIf; 103 import com.google.gwt.dev.js.ast.JsIntegralLiteral; 104 import com.google.gwt.dev.js.ast.JsInvocation; 105 import com.google.gwt.dev.js.ast.JsLabel; 106 import com.google.gwt.dev.js.ast.JsModVisitor; 107 import com.google.gwt.dev.js.ast.JsName; 108 import com.google.gwt.dev.js.ast.JsNameRef; 109 import com.google.gwt.dev.js.ast.JsNew; 110 import com.google.gwt.dev.js.ast.JsNode; 111 import com.google.gwt.dev.js.ast.JsObjectLiteral; 112 import com.google.gwt.dev.js.ast.JsParameter; 113 import com.google.gwt.dev.js.ast.JsParameters; 114 import com.google.gwt.dev.js.ast.JsPostfixOperation; 115 import com.google.gwt.dev.js.ast.JsPrefixOperation; 116 import com.google.gwt.dev.js.ast.JsProgram; 117 import com.google.gwt.dev.js.ast.JsPropertyInitializer; 118 import com.google.gwt.dev.js.ast.JsReturn; 119 import com.google.gwt.dev.js.ast.JsScope; 120 import com.google.gwt.dev.js.ast.JsStatement; 121 import com.google.gwt.dev.js.ast.JsStatements; 122 import com.google.gwt.dev.js.ast.JsStringLiteral; 123 import com.google.gwt.dev.js.ast.JsSwitch; 124 import com.google.gwt.dev.js.ast.JsSwitchMember; 125 import com.google.gwt.dev.js.ast.JsThisRef; 126 import com.google.gwt.dev.js.ast.JsThrow; 127 import com.google.gwt.dev.js.ast.JsTry; 128 import com.google.gwt.dev.js.ast.JsUnaryOperation; 129 import com.google.gwt.dev.js.ast.JsUnaryOperator; 130 import com.google.gwt.dev.js.ast.JsVars; 131 import com.google.gwt.dev.js.ast.JsWhile; 132 import com.google.gwt.dev.js.ast.JsVars.JsVar; 133 134 import java.math.BigInteger ; 135 import java.util.ArrayList ; 136 import java.util.Arrays ; 137 import java.util.Collections ; 138 import java.util.HashSet ; 139 import java.util.IdentityHashMap ; 140 import java.util.Iterator ; 141 import java.util.List ; 142 import java.util.Map ; 143 import java.util.Set ; 144 import java.util.Stack ; 145 import java.util.TreeMap ; 146 import java.util.Map.Entry; 147 148 151 public class GenerateJavaScriptAST { 152 153 private class CreateNamesAndScopesVisitor extends JVisitor { 154 155 private final Stack scopeStack = new Stack (); 156 157 public void endVisit(JClassType x, Context ctx) { 159 pop(); 160 } 161 162 public void endVisit(JField x, Context ctx) { 164 String name = x.getName(); 165 String mangleName = mangleName(x); 166 if (x.isStatic()) { 167 names.put(x, topScope.declareName(mangleName, name)); 168 } else { 169 names.put(x, peek().declareName(mangleName, name)); 170 } 171 } 172 173 public void endVisit(JInterfaceType x, Context ctx) { 175 pop(); 176 } 177 178 public void endVisit(JLabel x, Context ctx) { 180 if (getName(x) != null) { 181 return; 182 } 183 names.put(x, peek().declareName(x.getName())); 184 } 185 186 public void endVisit(JLocal x, Context ctx) { 188 JsScope scope = peek(); 190 JsName jsName = scope.declareName(x.getName()); 191 names.put(x, jsName); 192 } 193 194 public void endVisit(JMethod x, Context ctx) { 196 pop(); 197 } 198 199 public void endVisit(JParameter x, Context ctx) { 201 names.put(x, peek().declareName(x.getName())); 202 } 203 204 public void endVisit(JProgram x, Context ctx) { 206 JField field = x.getSpecialField("Object.typeId"); 208 names.put(field, objectScope.declareName(mangleName(field), 209 field.getName())); 210 211 field = x.getSpecialField("Object.typeName"); 212 names.put(field, objectScope.declareName(mangleName(field), 213 field.getName())); 214 215 field = x.getSpecialField("Cast.typeIdArray"); 216 names.put(field, topScope.declareName(mangleName(field), field.getName())); 217 218 222 JMethod nullMethod = x.getNullMethod(); 223 polymorphicNames.put(nullMethod, 224 objectScope.declareName(nullMethod.getName())); 225 JField nullField = x.getNullField(); 226 JsName nullFieldName = objectScope.declareName(nullField.getName()); 227 polymorphicNames.put(nullField, nullFieldName); 228 names.put(nullField, nullFieldName); 229 230 233 nullMethodName = topScope.declareName(nullMethod.getName()); 234 names.put(nullMethod, nullMethodName); 235 } 236 237 public void endVisit(JsniMethod x, Context ctx) { 239 } 241 242 public boolean visit(JClassType x, Context ctx) { 244 JsScope myScope = (JsScope) classScopes.get(x); 246 if (myScope != null) { 247 push(myScope); 248 return false; 249 } 250 251 names.put(x, topScope.declareName(getNameString(x), x.getShortName())); 253 254 if (x.extnds == null) { 256 myScope = objectScope; 257 } else { 258 JsScope parentScope = (JsScope) classScopes.get(x.extnds); 259 if (parentScope == null) { 261 accept(x.extnds); 262 } 263 parentScope = (JsScope) classScopes.get(x.extnds); 264 assert (parentScope != null); 265 270 if (parentScope == objectScope) { 271 parentScope = interfaceScope; 272 } 273 myScope = new JsScope(parentScope, "class " + x.getShortName()); 274 } 275 classScopes.put(x, myScope); 276 277 String packageName = getPackageName(x.getName()); 279 if (packageName != null && packageName.length() > 0) { 280 if (packageNames.get(packageName) == null) { 281 String ident = "package_" + packageName.replace('.', '_'); 282 JsName jsName = topScope.declareName(ident); 283 packageNames.put(packageName, jsName); 284 } 285 } 286 287 push(myScope); 288 return true; 289 } 290 291 public boolean visit(JInterfaceType x, Context ctx) { 293 push(interfaceScope); 295 return true; 296 } 297 298 public boolean visit(JMethod x, Context ctx) { 300 301 String name = x.getName(); 303 if (!x.isStatic()) { 304 if (getPolyName(x) == null) { 305 String mangleName = mangleNameForPoly(x); 306 JsName polyName = interfaceScope.declareName(mangleName, name); 307 polymorphicNames.put(x, polyName); 308 } 309 } 310 311 if (x.isAbstract()) { 312 push(null); 314 return false; 315 } 316 317 JsName globalName; 319 if (x.getEnclosingType() == null) { 320 globalName = topScope.declareName(name); 321 } else { 322 String mangleName = mangleNameForGlobal(x); 323 globalName = topScope.declareName(mangleName, name); 324 } 325 names.put(x, globalName); 326 327 JsFunction jsFunction = new JsFunction(topScope, globalName); 329 methodMap.put(x, jsFunction); 330 331 push(jsFunction.getScope()); 332 return true; 333 } 334 335 public boolean visit(JsniMethod x, Context ctx) { 337 String name = x.getName(); 339 if (!x.isStatic()) { 340 if (getPolyName(x) == null) { 341 String mangleName = mangleNameForPoly(x); 342 JsName polyName = interfaceScope.declareName(mangleName, name); 343 polymorphicNames.put(x, polyName); 344 } 345 } 346 347 String fnName = mangleNameForGlobal(x); 349 JsName globalName = topScope.declareName(fnName, name); 350 x.getFunc().setName(globalName); 351 names.put(x, globalName); 352 353 return false; 354 } 355 356 public boolean visit(JTryStatement x, Context ctx) { 357 accept(x.getTryBlock()); 358 359 List catchArgs = x.getCatchArgs(); 360 List catchBlocks = x.getCatchBlocks(); 361 for (int i = 0, c = catchArgs.size(); i < c; ++i) { 362 JLocalRef arg = (JLocalRef) catchArgs.get(i); 363 JBlock catchBlock = (JBlock) catchBlocks.get(i); 364 JsCatch jsCatch = new JsCatch(peek(), arg.getTarget().getName()); 365 JsParameter jsParam = jsCatch.getParameter(); 366 names.put(arg.getTarget(), jsParam.getName()); 367 catchMap.put(catchBlock, jsCatch); 368 369 push(jsCatch.getScope()); 370 accept(catchBlock); 371 pop(); 372 } 373 374 if (x.getFinallyBlock() != null) { 376 accept(x.getFinallyBlock()); 377 } 378 return false; 379 } 380 381 private JsScope peek() { 382 return (JsScope) scopeStack.peek(); 383 } 384 385 private void pop() { 386 scopeStack.pop(); 387 } 388 389 private void push(JsScope scope) { 390 scopeStack.push(scope); 391 } 392 } 393 394 private class GenerateJavaScriptVisitor extends JVisitor { 395 396 private final Set alreadyRan = new HashSet (); 397 398 private JMethod currentMethod = null; 399 400 private final JsName globalTemp = topScope.declareName("_"); 401 402 private final Stack nodeStack = new Stack (); 403 404 private final JsName prototype = objectScope.declareName("prototype"); 405 406 { 407 globalTemp.setObfuscatable(false); 408 prototype.setObfuscatable(false); 409 } 410 411 public void endVisit(JAbsentArrayDimension x, Context ctx) { 413 throw new InternalCompilerException("Should not get here."); 414 } 415 416 public void endVisit(JArrayRef x, Context ctx) { 418 JsArrayAccess jsArrayAccess = new JsArrayAccess(); 419 jsArrayAccess.setIndexExpr((JsExpression) pop()); 420 jsArrayAccess.setArrayExpr((JsExpression) pop()); 421 push(jsArrayAccess); 422 } 423 424 public void endVisit(JAssertStatement x, Context ctx) { 426 throw new InternalCompilerException("Should not get here."); 427 } 428 429 public void endVisit(JBinaryOperation x, Context ctx) { 431 JsExpression rhs = (JsExpression) pop(); JsExpression lhs = (JsExpression) pop(); JsBinaryOperator myOp = JavaToJsOperatorMap.get(x.getOp()); 434 435 439 if (myOp == JsBinaryOperator.EQ 440 && x.getLhs().getType() instanceof JReferenceType 441 && x.getRhs().getType() instanceof JReferenceType) { 442 myOp = JsBinaryOperator.REF_EQ; 443 } else if (myOp == JsBinaryOperator.NEQ 444 && x.getLhs().getType() instanceof JReferenceType 445 && x.getRhs().getType() instanceof JReferenceType) { 446 myOp = JsBinaryOperator.REF_NEQ; 447 } 448 449 push(new JsBinaryOperation(myOp, lhs, rhs)); 450 } 451 452 public void endVisit(JBlock x, Context ctx) { 454 JsBlock jsBlock = new JsBlock(); 455 JsStatements stmts = jsBlock.getStatements(); 456 popList(stmts, x.statements.size()); Iterator iterator = stmts.iterator(); 458 while (iterator.hasNext()) { 459 JsStatement stmt = (JsStatement) iterator.next(); 460 if (stmt == jsProgram.getEmptyStmt()) { 461 iterator.remove(); 462 } 463 } 464 push(jsBlock); 465 } 466 467 public void endVisit(JBooleanLiteral x, Context ctx) { 469 push(x.getValue() ? jsProgram.getTrueLiteral() 470 : jsProgram.getFalseLiteral()); 471 } 472 473 public void endVisit(JBreakStatement x, Context ctx) { 475 JsNameRef labelRef = null; 476 if (x.getLabel() != null) { 477 JsLabel label = (JsLabel) pop(); labelRef = label.getName().makeRef(); 479 } 480 push(new JsBreak(labelRef)); 481 } 482 483 public void endVisit(JCaseStatement x, Context ctx) { 485 if (x.getExpr() == null) { 486 push(new JsDefault()); 487 } else { 488 JsCase jsCase = new JsCase(); 489 jsCase.setCaseExpr((JsExpression) pop()); push(jsCase); 491 } 492 } 493 494 public void endVisit(JCastOperation x, Context ctx) { 496 throw new InternalCompilerException("Should not get here."); 497 } 498 499 public void endVisit(JCharLiteral x, Context ctx) { 501 push(jsProgram.getIntegralLiteral(BigInteger.valueOf(x.getValue()))); 502 } 503 504 public void endVisit(JClassLiteral x, Context ctx) { 506 String nameString = x.getRefType().getJavahSignatureName() + "_classlit"; 508 JsName classLit = topScope.declareName(nameString); 509 classLits.put(x.getRefType(), classLit); 510 push(classLit.makeRef()); 511 } 512 513 public void endVisit(JClassSeed x, Context ctx) { 515 push(getName(x.getRefType()).makeRef()); 516 } 517 518 public void endVisit(JClassType x, Context ctx) { 520 if (alreadyRan.contains(x)) { 521 return; 522 } 523 524 alreadyRan.add(x); 525 526 List jsFuncs = popList(x.methods.size()); List jsFields = popList(x.fields.size()); 529 if (typeOracle.hasDirectClinit(x)) { 530 JClassType superType = x.extnds; 532 while (superType != null && !typeOracle.hasDirectClinit(superType)) { 533 superType = superType.extnds; 534 } 535 handleClinit((JsFunction) jsFuncs.get(0), superType); 536 } else { 537 jsFuncs.set(0, null); 538 } 539 540 JsStatements globalStmts = jsProgram.getGlobalBlock().getStatements(); 541 542 for (int i = 0; i < jsFuncs.size(); ++i) { 544 JsFunction func = (JsFunction) jsFuncs.get(i); 545 if (func != null) { 546 globalStmts.add(func.makeStmt()); 547 } 548 } 549 550 if (typeOracle.isInstantiatedType(x)) { 551 generateClassSetup(x, globalStmts); 552 } 553 554 JsVars vars = new JsVars(); 556 for (int i = 0; i < jsFields.size(); ++i) { 557 JsNode node = (JsNode) jsFields.get(i); 558 if (node instanceof JsVar) { 559 vars.add((JsVar) node); 560 } else { 561 assert (node instanceof JsStatement); 562 JsStatement stmt = (JsStatement) jsFields.get(i); 563 globalStmts.add(stmt); 564 } 565 } 566 if (!vars.isEmpty()) { 567 globalStmts.add(vars); 568 } 569 } 570 571 public void endVisit(JConditional x, Context ctx) { 573 JsExpression elseExpr = (JsExpression) pop(); JsExpression thenExpr = (JsExpression) pop(); JsExpression ifTest = (JsExpression) pop(); push(new JsConditional(ifTest, thenExpr, elseExpr)); 577 } 578 579 public void endVisit(JContinueStatement x, Context ctx) { 581 JsNameRef labelRef = null; 582 if (x.getLabel() != null) { 583 JsLabel label = (JsLabel) pop(); labelRef = label.getName().makeRef(); 585 } 586 push(new JsContinue(labelRef)); 587 } 588 589 public void endVisit(JDoStatement x, Context ctx) { 591 JsDoWhile stmt = new JsDoWhile(); 592 if (x.getBody() != null) { 593 stmt.setBody((JsStatement) pop()); } else { 595 stmt.setBody(jsProgram.getEmptyStmt()); 596 } 597 stmt.setCondition((JsExpression) pop()); push(stmt); 599 } 600 601 public void endVisit(JDoubleLiteral x, Context ctx) { 603 push(jsProgram.getDecimalLiteral(String.valueOf(x.getValue()))); 604 } 605 606 public void endVisit(JExpressionStatement x, Context ctx) { 608 JsExpression expr = (JsExpression) pop(); push(expr.makeStmt()); 610 } 611 612 public void endVisit(JField x, Context ctx) { 614 if (x.constInitializer != null) { 616 accept(x.constInitializer); 618 } else if (!x.hasInitializer()) { 619 accept(x.getType().getDefaultValue()); 621 } else { 622 push(null); 624 } 625 JsExpression rhs = (JsExpression) pop(); 626 JsName name = getName(x); 627 628 if (x.isStatic()) { 629 JsVar var = new JsVar(name); 631 var.setInitExpr(rhs); 632 push(var); 633 } else { 634 if (rhs != null) { 636 JsNameRef fieldRef = name.makeRef(); 637 fieldRef.setQualifier(globalTemp.makeRef()); 638 JsExpression asg = createAssignment(fieldRef, rhs); 639 push(new JsExprStmt(asg)); 640 } else { 641 push(null); 642 } 643 } 644 } 645 646 public void endVisit(JFieldRef x, Context ctx) { 648 JField field = x.getField(); 649 JsName jsFieldName = getName(field); 650 JsNameRef nameRef = jsFieldName.makeRef(); 651 JsExpression curExpr = nameRef; 652 653 658 659 JsInvocation jsInvocation = maybeCreateClinitCall(field); 661 if (jsInvocation != null) { 662 curExpr = createCommaExpression(jsInvocation, curExpr); 663 } 664 665 if (x.getInstance() != null) { 666 JsExpression qualifier = (JsExpression) pop(); 667 if (field.isStatic()) { 668 curExpr = createCommaExpression(qualifier, curExpr); 670 } else { 671 nameRef.setQualifier(qualifier); 673 } 674 } 675 676 push(curExpr); 677 } 678 679 public void endVisit(JFloatLiteral x, Context ctx) { 681 push(jsProgram.getDecimalLiteral(String.valueOf(x.getValue()))); 682 } 683 684 public void endVisit(JForStatement x, Context ctx) { 686 JsFor jsFor = new JsFor(); 687 688 if (x.getBody() != null) { 690 jsFor.setBody((JsStatement) pop()); 691 } else { 692 jsFor.setBody(jsProgram.getEmptyStmt()); 693 } 694 695 { 697 JsExpression incrExpr = null; 698 List exprStmts = popList(x.getIncrements().size()); 699 for (int i = 0; i < exprStmts.size(); ++i) { 700 JsExprStmt exprStmt = (JsExprStmt) exprStmts.get(i); 701 incrExpr = createCommaExpression(incrExpr, exprStmt.getExpression()); 702 } 703 jsFor.setIncrExpr(incrExpr); 704 } 705 706 if (x.getTestExpr() != null) { 708 jsFor.setCondition((JsExpression) pop()); 709 } 710 711 JsExpression initExpr = null; 713 List initStmts = popList(x.getInitializers().size()); 714 for (int i = 0; i < initStmts.size(); ++i) { 715 JsExprStmt initStmt = (JsExprStmt) initStmts.get(i); 716 if (initStmt != null) { 717 initExpr = createCommaExpression(initExpr, initStmt.getExpression()); 718 } 719 } 720 jsFor.setInitExpr(initExpr); 721 722 push(jsFor); 723 } 724 725 public void endVisit(JIfStatement x, Context ctx) { 727 JsIf stmt = new JsIf(); 728 729 if (x.getElseStmt() != null) { 730 stmt.setElseStmt((JsStatement) pop()); } 732 733 if (x.getThenStmt() != null) { 734 stmt.setThenStmt((JsStatement) pop()); } else { 736 stmt.setThenStmt(jsProgram.getEmptyStmt()); 737 } 738 739 stmt.setIfExpr((JsExpression) pop()); push(stmt); 741 } 742 743 public void endVisit(JInstanceOf x, Context ctx) { 745 throw new InternalCompilerException("Should not get here."); 746 } 747 748 public void endVisit(JInterfaceType x, Context ctx) { 750 List jsFuncs = popList(x.methods.size()); List jsFields = popList(x.fields.size()); 753 JsStatements globalStmts = jsProgram.getGlobalBlock().getStatements(); 754 755 if (typeOracle.hasDirectClinit(x)) { 756 JsFunction clinitFunc = (JsFunction) jsFuncs.get(0); 757 handleClinit(clinitFunc, null); 758 globalStmts.add(clinitFunc.makeStmt()); 759 } 760 761 JsVars vars = new JsVars(); 763 for (int i = 0; i < jsFields.size(); ++i) { 764 JsNode node = (JsNode) jsFields.get(i); 765 assert (node instanceof JsVar); 766 vars.add((JsVar) node); 767 } 768 if (!vars.isEmpty()) { 769 globalStmts.add(vars); 770 } 771 } 772 773 public void endVisit(JIntLiteral x, Context ctx) { 775 push(jsProgram.getIntegralLiteral(BigInteger.valueOf(x.getValue()))); 776 } 777 778 public void endVisit(JLabel x, Context ctx) { 780 push(new JsLabel(getName(x))); 781 } 782 783 public void endVisit(JLabeledStatement x, Context ctx) { 785 JsStatement body = (JsStatement) pop(); JsLabel label = (JsLabel) pop(); label.setStmt(body); 788 push(label); 789 } 790 791 public void endVisit(JLocal x, Context ctx) { 793 push(getName(x).makeRef()); 794 } 795 796 public void endVisit(JLocalDeclarationStatement x, Context ctx) { 798 799 if (x.getInitializer() == null) { 800 pop(); 805 push(null); 806 return; 807 } 808 809 JsExpression initializer = (JsExpression) pop(); JsNameRef localRef = (JsNameRef) pop(); 812 JsBinaryOperation binOp = new JsBinaryOperation(JsBinaryOperator.ASG, 813 localRef, initializer); 814 815 push(binOp.makeStmt()); 816 } 817 818 public void endVisit(JLocalRef x, Context ctx) { 820 push(getName(x.getTarget()).makeRef()); 821 } 822 823 public void endVisit(JLongLiteral x, Context ctx) { 825 push(jsProgram.getIntegralLiteral(BigInteger.valueOf(x.getValue()))); 826 } 827 828 public void endVisit(JMethod x, Context ctx) { 830 831 JsBlock body = (JsBlock) pop(); 832 List locals = popList(x.locals.size()); List params = popList(x.params.size()); 835 if (x.isAbstract()) { 836 push(null); 837 return; 838 } 839 840 JsFunction jsFunc = (JsFunction) methodMap.get(x); 841 jsFunc.setBody(body); 843 JsParameters jsParams = jsFunc.getParameters(); 844 for (int i = 0; i < params.size(); ++i) { 845 JsParameter param = (JsParameter) params.get(i); 846 jsParams.add(param); 847 } 848 849 861 JsVars vars = new JsVars(); 862 Set alreadySeen = new HashSet (); 863 for (int i = 0; i < locals.size(); ++i) { 864 JsName name = (JsName) names.get(x.locals.get(i)); 865 String ident = name.getIdent(); 866 if (!alreadySeen.contains(ident)) { 867 alreadySeen.add(ident); 868 vars.add(new JsVar(name)); 869 } 870 } 871 872 if (!vars.isEmpty()) { 873 jsFunc.getBody().getStatements().add(0, vars); 874 } 875 876 JsInvocation jsInvocation = maybeCreateClinitCall(x); 877 if (jsInvocation != null) { 878 jsFunc.getBody().getStatements().add(0, jsInvocation.makeStmt()); 879 } 880 881 push(jsFunc); 882 currentMethod = null; 883 } 884 885 public void endVisit(JMethodCall x, Context ctx) { 887 JMethod method = x.getTarget(); 888 JsInvocation jsInvocation = new JsInvocation(); 889 890 popList(jsInvocation.getArguments(), x.getArgs().size()); 892 JsNameRef qualifier; 893 JsExpression unnecessaryQualifier = null; 894 if (method.isStatic()) { 895 if (x.getInstance() != null) { 896 unnecessaryQualifier = (JsExpression) pop(); } 898 qualifier = getName(method).makeRef(); 899 } else { 900 if (x.isStaticDispatchOnly()) { 901 910 JsName callName = objectScope.declareName("call"); 911 callName.setObfuscatable(false); 912 qualifier = callName.makeRef(); 913 qualifier.setQualifier(getName(method).makeRef()); 914 jsInvocation.getArguments().add(0, (JsExpression) pop()); } else { 916 qualifier = getPolyName(method).makeRef(); 918 qualifier.setQualifier((JsExpression) pop()); } 920 } 921 jsInvocation.setQualifier(qualifier); 922 push(createCommaExpression(unnecessaryQualifier, jsInvocation)); 923 } 924 925 public void endVisit(JMultiExpression x, Context ctx) { 927 List exprs = popList(x.exprs.size()); 928 JsExpression cur = null; 929 for (int i = 0; i < exprs.size(); ++i) { 930 JsExpression next = (JsExpression) exprs.get(i); 931 cur = createCommaExpression(cur, next); 932 } 933 push(cur); 934 } 935 936 public void endVisit(JNewArray x, Context ctx) { 938 throw new InternalCompilerException("Should not get here."); 939 } 940 941 public void endVisit(JNewInstance x, Context ctx) { 943 JsNew newOp = new JsNew(); 944 JsNameRef nameRef = getName(x.getType()).makeRef(); 945 newOp.setConstructorExpression(nameRef); 946 push(newOp); 947 } 948 949 public void endVisit(JNullLiteral x, Context ctx) { 951 push(jsProgram.getNullLiteral()); 952 } 953 954 public void endVisit(JParameter x, Context ctx) { 956 push(new JsParameter(getName(x))); 957 } 958 959 public void endVisit(JParameterRef x, Context ctx) { 961 push(getName(x.getTarget()).makeRef()); 962 } 963 964 public void endVisit(JPostfixOperation x, Context ctx) { 966 JsUnaryOperation op = new JsPostfixOperation( 967 JavaToJsOperatorMap.get(x.getOp()), ((JsExpression) pop())); push(op); 969 } 970 971 public void endVisit(JPrefixOperation x, Context ctx) { 973 JsUnaryOperation op = new JsPrefixOperation( 974 JavaToJsOperatorMap.get(x.getOp()), ((JsExpression) pop())); push(op); 976 } 977 978 public void endVisit(JProgram x, Context ctx) { 980 JsStatements globalStmts = jsProgram.getGlobalBlock().getStatements(); 981 982 984 List entryFuncs = popList(x.entryMethods.size()); for (int i = 0; i < entryFuncs.size(); ++i) { 987 JsFunction func = (JsFunction) entryFuncs.get(i); 988 if (func != null) { 989 globalStmts.add(func.makeStmt()); 990 } 991 } 992 993 generateGwtOnLoad(entryFuncs, globalStmts); 994 995 JsVars vars = new JsVars(); 997 generateTypeTable(vars); 998 generateClassLiterals(vars); 999 globalStmts.add(vars); 1000 } 1001 1002 public void endVisit(JReturnStatement x, Context ctx) { 1004 if (x.getExpr() != null) { 1005 push(new JsReturn((JsExpression) pop())); } else { 1007 push(new JsReturn()); 1008 } 1009 } 1010 1011 public void endVisit(JsniMethod x, Context ctx) { 1013 JsFunction jsFunc = x.getFunc(); 1014 1015 new JsModVisitor() { 1017 public void endVisit(JsNameRef x, JsContext ctx) { 1019 String ident = x.getIdent(); 1020 if (ident.charAt(0) == '@') { 1021 HasEnclosingType node = (HasEnclosingType) program.jsniMap.get(ident); 1022 assert (node != null); 1023 if (node instanceof JField) { 1024 JField field = (JField) node; 1025 JsName jsName = getName(field); 1026 assert (jsName != null); 1027 x.resolve(jsName); 1028 1029 JsInvocation clinitCall = maybeCreateClinitCall(field); 1031 if (clinitCall != null) { 1032 JsExpression commaExpr = createCommaExpression(clinitCall, x); 1033 ctx.replaceMe(commaExpr); 1034 } 1035 } else { 1036 JMethod method = (JMethod) node; 1037 if (x.getQualifier() == null) { 1038 JsName jsName = getName(method); 1039 assert (jsName != null); 1040 x.resolve(jsName); 1041 } else { 1042 JsName jsName = getPolyName(method); 1043 if (jsName == null) { 1044 jsName = nullMethodName; 1047 } 1048 x.resolve(jsName); 1049 } 1050 } 1051 } 1052 } 1053 }.accept(jsFunc); 1054 1055 JsInvocation jsInvocation = maybeCreateClinitCall(x); 1056 if (jsInvocation != null) { 1057 jsFunc.getBody().getStatements().add(0, jsInvocation.makeStmt()); 1058 } 1059 1060 push(jsFunc); 1061 currentMethod = null; 1062 } 1063 1064 public void endVisit(JsonArray x, Context ctx) { 1066 JsArrayLiteral jsArrayLiteral = new JsArrayLiteral(); 1067 popList(jsArrayLiteral.getExpressions(), x.exprs.size()); 1068 push(jsArrayLiteral); 1069 } 1070 1071 public void endVisit(JsonObject x, Context ctx) { 1073 JsObjectLiteral jsObjectLiteral = new JsObjectLiteral(); 1074 popList(jsObjectLiteral.getPropertyInitializers(), x.propInits.size()); 1075 push(jsObjectLiteral); 1076 } 1077 1078 public void endVisit(JsonPropInit init, Context ctx) { 1080 JsExpression valueExpr = (JsExpression) pop(); 1081 JsExpression labelExpr = (JsExpression) pop(); 1082 push(new JsPropertyInitializer(labelExpr, valueExpr)); 1083 } 1084 1085 public void endVisit(JStringLiteral x, Context ctx) { 1087 push(jsProgram.getStringLiteral(x.getValue())); 1088 } 1089 1090 public void endVisit(JThisRef x, Context ctx) { 1092 push(new JsThisRef()); 1093 } 1094 1095 public void endVisit(JThrowStatement x, Context ctx) { 1097 push(new JsThrow((JsExpression) pop())); } 1099 1100 public void endVisit(JTryStatement x, Context ctx) { 1102 JsTry jsTry = new JsTry(); 1103 1104 if (x.getFinallyBlock() != null) { 1105 JsBlock finallyBlock = (JsBlock) pop(); if (finallyBlock.getStatements().size() > 0) { 1107 jsTry.setFinallyBlock(finallyBlock); 1108 } 1109 } 1110 1111 int size = x.getCatchArgs().size(); 1112 assert (size < 2 && size == x.getCatchBlocks().size()); 1113 if (size == 1) { 1114 JsBlock catchBlock = (JsBlock) pop(); pop(); JsCatch jsCatch = (JsCatch) catchMap.get(x.getCatchBlocks().get(0)); 1117 jsCatch.setBody(catchBlock); 1118 jsTry.getCatches().add(jsCatch); 1119 } 1120 1121 jsTry.setTryBlock((JsBlock) pop()); 1123 push(jsTry); 1124 } 1125 1126 public void endVisit(JWhileStatement x, Context ctx) { 1128 JsWhile stmt = new JsWhile(); 1129 if (x.getBody() != null) { 1130 stmt.setBody((JsStatement) pop()); } else { 1132 stmt.setBody(jsProgram.getEmptyStmt()); 1133 } 1134 stmt.setCondition((JsExpression) pop()); push(stmt); 1136 } 1137 1138 public boolean visit(JClassType x, Context ctx) { 1140 if (alreadyRan.contains(x)) { 1141 return false; 1142 } 1143 1144 if (x.extnds != null && !alreadyRan.contains(x)) { 1147 accept(x.extnds); 1148 } 1149 1150 return true; 1151 } 1152 1153 public boolean visit(JMethod x, Context ctx) { 1155 currentMethod = x; 1156 return true; 1157 } 1158 1159 public boolean visit(JProgram x, Context ctx) { 1161 JsStatements globalStatements = jsProgram.getGlobalBlock().getStatements(); 1162 1163 JsVars vars = new JsVars(); 1165 1166 vars.add(new JsVar(globalTemp)); 1168 generatePackageNames(vars); 1169 globalStatements.add(vars); 1170 1171 generateNullFunc(globalStatements); 1172 return true; 1173 } 1174 1175 public boolean visit(JsniMethod x, Context ctx) { 1177 currentMethod = x; 1178 return false; 1179 } 1180 1181 public boolean visit(JSwitchStatement x, Context ctx) { 1182 1186 JsSwitch jsSwitch = new JsSwitch(); 1187 accept(x.getExpr()); 1188 jsSwitch.setExpr((JsExpression) pop()); 1190 List bodyStmts = x.getBody().statements; 1191 if (bodyStmts.size() > 0) { 1192 JsStatements curStatements = null; 1193 for (int i = 0; i < bodyStmts.size(); ++i) { 1194 JStatement stmt = (JStatement) bodyStmts.get(i); 1195 accept(stmt); 1196 if (stmt instanceof JCaseStatement) { 1197 JsSwitchMember switchMember = (JsSwitchMember) pop(); jsSwitch.getCases().add(switchMember); 1200 curStatements = switchMember.getStmts(); 1201 } else { 1202 assert (curStatements != null); 1204 JsStatement newStmt = (JsStatement) pop(); if (newStmt != null) { 1206 curStatements.add(newStmt); 1208 } 1209 } 1210 } 1211 } 1212 1213 push(jsSwitch); 1214 return false; 1215 } 1216 1217 private JsExpression createAssignment(JsExpression lhs, JsExpression rhs) { 1218 return new JsBinaryOperation(JsBinaryOperator.ASG, lhs, rhs); 1219 } 1220 1221 private JsExpression createCommaExpression(JsExpression lhs, 1222 JsExpression rhs) { 1223 if (lhs == null) { 1224 return rhs; 1225 } else if (rhs == null) { 1226 return lhs; 1227 } 1228 return new JsBinaryOperation(JsBinaryOperator.COMMA, lhs, rhs); 1229 } 1230 1231 private void generateClassLiterals(JsVars vars) { 1232 1236 for (Iterator itType = classLits.keySet().iterator(); itType.hasNext();) { 1237 JType type = (JType) itType.next(); 1238 JsName jsName = (JsName) classLits.get(type); 1239 String string; 1240 if (type instanceof JArrayType) { 1241 string = "class " + type.getJsniSignatureName().replace('/', '.'); 1242 } else if (type instanceof JClassType) { 1243 string = "class " + type.getName(); 1244 } else if (type instanceof JInterfaceType) { 1245 string = "interface " + type.getName(); 1246 } else { 1247 string = type.getName(); 1248 } 1249 JsStringLiteral stringLiteral = jsProgram.getStringLiteral(string); 1250 JsVar var = new JsVar(jsName); 1251 var.setInitExpr(stringLiteral); 1252 vars.add(var); 1253 } 1254 } 1255 1256 private void generateClassSetup(JClassType x, JsStatements globalStmts) { 1257 generateSeedFuncAndPrototype(x, globalStmts); 1258 generateVTables(x, globalStmts); 1259 1260 if (x == program.getTypeJavaLangObject()) { 1261 generateToStringAlias(x, globalStmts); 1263 } 1264 1265 generateTypeName(x, globalStmts); 1266 generateTypeId(x, globalStmts); 1267 } 1268 1269 private void generateGwtOnLoad(List entryFuncs, JsStatements globalStmts) { 1270 1287 JsFunction gwtOnLoad = new JsFunction(topScope); 1288 globalStmts.add(gwtOnLoad.makeStmt()); 1289 JsName gwtOnLoadName = topScope.declareName("gwtOnLoad"); 1290 gwtOnLoadName.setObfuscatable(false); 1291 gwtOnLoad.setName(gwtOnLoadName); 1292 JsBlock body = new JsBlock(); 1293 gwtOnLoad.setBody(body); 1294 JsScope fnScope = gwtOnLoad.getScope(); 1295 JsParameters params = gwtOnLoad.getParameters(); 1296 JsName errFn = fnScope.declareName("errFn"); 1297 JsName modName = fnScope.declareName("modName"); 1298 JsName modBase = fnScope.declareName("modBase"); 1299 params.add(new JsParameter(errFn)); 1300 params.add(new JsParameter(modName)); 1301 params.add(new JsParameter(modBase)); 1302 JsExpression asg = createAssignment( 1303 topScope.findExistingUnobfuscatableName("$moduleName").makeRef(), 1304 modName.makeRef()); 1305 body.getStatements().add(asg.makeStmt()); 1306 asg = createAssignment(topScope.findExistingUnobfuscatableName( 1307 "$moduleBase").makeRef(), modBase.makeRef()); 1308 body.getStatements().add(asg.makeStmt()); 1309 JsIf jsIf = new JsIf(); 1310 body.getStatements().add(jsIf); 1311 jsIf.setIfExpr(errFn.makeRef()); 1312 JsTry jsTry = new JsTry(); 1313 jsIf.setThenStmt(jsTry); 1314 JsBlock callBlock = new JsBlock(); 1315 jsIf.setElseStmt(callBlock); 1316 jsTry.setTryBlock(callBlock); 1317 for (int i = 0; i < entryFuncs.size(); ++i) { 1318 JsFunction func = (JsFunction) entryFuncs.get(i); 1319 if (func != null) { 1320 JsInvocation call = new JsInvocation(); 1321 call.setQualifier(func.getName().makeRef()); 1322 callBlock.getStatements().add(call.makeStmt()); 1323 } 1324 } 1325 JsCatch jsCatch = new JsCatch(fnScope, "e"); 1326 jsTry.getCatches().add(jsCatch); 1327 JsBlock catchBlock = new JsBlock(); 1328 jsCatch.setBody(catchBlock); 1329 JsInvocation errCall = new JsInvocation(); 1330 catchBlock.getStatements().add(errCall.makeStmt()); 1331 errCall.setQualifier(errFn.makeRef()); 1332 errCall.getArguments().add(modName.makeRef()); 1333 } 1334 1335 private void generateNullFunc(JsStatements globalStatements) { 1336 JsFunction nullFunc = new JsFunction(topScope, nullMethodName); 1338 nullFunc.setBody(new JsBlock()); 1339 globalStatements.add(nullFunc.makeStmt()); 1340 } 1341 1342 private void generatePackageNames(JsVars vars) { 1343 for (Iterator it = packageNames.entrySet().iterator(); it.hasNext();) { 1344 Map.Entry entry = (Entry) it.next(); 1345 String packageName = (String ) entry.getKey(); 1346 JsName name = (JsName) entry.getValue(); 1347 JsVar jsVar = new JsVar(name); 1348 jsVar.setInitExpr(jsProgram.getStringLiteral(packageName)); 1349 vars.add(jsVar); 1350 } 1351 } 1352 1353 private void generateSeedFuncAndPrototype(JClassType x, 1354 JsStatements globalStmts) { 1355 if (x != program.getTypeJavaLangString()) { 1356 JsName seedFuncName = getName(x); 1357 1358 JsFunction seedFunc = new JsFunction(topScope, seedFuncName); 1361 JsBlock body = new JsBlock(); 1362 seedFunc.setBody(body); 1363 globalStmts.add(seedFunc.makeStmt()); 1364 1365 JsNameRef lhs = prototype.makeRef(); 1368 lhs.setQualifier(seedFuncName.makeRef()); 1369 JsExpression rhs; 1370 if (x.extnds != null) { 1371 JsNew newExpr = new JsNew(); 1372 newExpr.setConstructorExpression(getName(x.extnds).makeRef()); 1373 rhs = newExpr; 1374 } else { 1375 rhs = new JsObjectLiteral(); 1376 } 1377 JsExpression protoAsg = createAssignment(lhs, rhs); 1378 JsExpression tmpAsg = createAssignment(globalTemp.makeRef(), protoAsg); 1379 globalStmts.add(tmpAsg.makeStmt()); 1380 } else { 1381 1385 JsNameRef rhs = prototype.makeRef(); 1386 rhs.setQualifier(jsProgram.getRootScope().declareName("String").makeRef()); 1387 JsExpression tmpAsg = createAssignment(globalTemp.makeRef(), rhs); 1388 globalStmts.add(tmpAsg.makeStmt()); 1389 } 1390 } 1391 1392 private void generateToStringAlias(JClassType x, JsStatements globalStmts) { 1393 JMethod toStringMeth = program.getSpecialMethod("Object.toString"); 1394 if (x.methods.contains(toStringMeth)) { 1395 1397 JsName lhsName = objectScope.declareName("toString"); 1399 lhsName.setObfuscatable(false); 1400 JsNameRef lhs = lhsName.makeRef(); 1401 lhs.setQualifier(globalTemp.makeRef()); 1402 1403 JsInvocation call = new JsInvocation(); 1405 JsNameRef toStringRef = new JsNameRef(getPolyName(toStringMeth)); 1406 toStringRef.setQualifier(new JsThisRef()); 1407 call.setQualifier(toStringRef); 1408 JsReturn jsReturn = new JsReturn(call); 1409 JsFunction rhs = new JsFunction(topScope); 1410 JsBlock body = new JsBlock(); 1411 body.getStatements().add(jsReturn); 1412 rhs.setBody(body); 1413 1414 JsExpression asg = createAssignment(lhs, rhs); 1416 globalStmts.add(new JsExprStmt(asg)); 1417 } 1418 } 1419 1420 private void generateTypeId(JClassType x, JsStatements globalStmts) { 1421 int typeId = program.getTypeId(x); 1422 if (typeId >= 0) { 1423 JField typeIdField = program.getSpecialField("Object.typeId"); 1424 JsNameRef fieldRef = getName(typeIdField).makeRef(); 1425 fieldRef.setQualifier(globalTemp.makeRef()); 1426 JsIntegralLiteral typeIdLit = jsProgram.getIntegralLiteral(BigInteger.valueOf(typeId)); 1427 JsExpression asg = createAssignment(fieldRef, typeIdLit); 1428 globalStmts.add(new JsExprStmt(asg)); 1429 } 1430 } 1431 1432 private void generateTypeName(JClassType x, JsStatements globalStmts) { 1433 JField typeIdField = program.getSpecialField("Object.typeName"); 1434 JsNameRef lhs = getName(typeIdField).makeRef(); 1435 lhs.setQualifier(globalTemp.makeRef()); 1436 1437 String className = getClassName(x.getName()); 1440 String packageName = getPackageName(x.getName()); 1441 JsExpression rhs; 1442 if (packageName != null) { 1443 JsName name = (JsName) packageNames.get(packageName); 1445 rhs = new JsBinaryOperation(JsBinaryOperator.ADD, name.makeRef(), 1446 jsProgram.getStringLiteral(className)); 1447 } else { 1448 rhs = jsProgram.getStringLiteral(x.getName()); 1450 } 1451 JsExpression asg = createAssignment(lhs, rhs); 1452 globalStmts.add(new JsExprStmt(asg)); 1453 } 1454 1455 private void generateTypeTable(JsVars vars) { 1456 JField typeIdArray = program.getSpecialField("Cast.typeIdArray"); 1457 JsName jsName = getName(typeIdArray); 1458 JsArrayLiteral arrayLit = new JsArrayLiteral(); 1459 for (int i = 0; i < program.getJsonTypeTable().size(); ++i) { 1460 JsonObject jsonObject = (JsonObject) program.getJsonTypeTable().get(i); 1461 accept(jsonObject); 1462 arrayLit.getExpressions().add((JsExpression) pop()); 1463 } 1464 JsVar var = new JsVar(jsName); 1465 var.setInitExpr(arrayLit); 1466 vars.add(var); 1467 } 1468 1469 private void generateVTables(JClassType x, JsStatements globalStmts) { 1470 for (int i = 0; i < x.methods.size(); ++i) { 1471 JMethod method = (JMethod) x.methods.get(i); 1472 if (!method.isStatic() && !method.isAbstract()) { 1473 JsNameRef lhs = getPolyName(method).makeRef(); 1474 lhs.setQualifier(globalTemp.makeRef()); 1475 JsNameRef rhs = getName(method).makeRef(); 1476 JsExpression asg = createAssignment(lhs, rhs); 1477 globalStmts.add(new JsExprStmt(asg)); 1478 } 1479 } 1480 } 1481 1482 private void handleClinit(JsFunction clinitFunc, JReferenceType chainTo) { 1483 JsStatements statements = clinitFunc.getBody().getStatements(); 1484 JsExpression asg = createAssignment(clinitFunc.getName().makeRef(), 1486 nullMethodName.makeRef()); 1487 statements.add(0, asg.makeStmt()); 1488 if (chainTo != null) { 1489 JMethod chainToMeth = (JMethod) chainTo.methods.get(0); 1490 JsInvocation jsInvocation = new JsInvocation(); 1491 JsNameRef qualifier = getName(chainToMeth).makeRef(); 1492 jsInvocation.setQualifier(qualifier); 1493 statements.add(1, jsInvocation.makeStmt()); 1494 } 1495 } 1496 1497 private JsInvocation maybeCreateClinitCall(JField x) { 1498 if (!x.isStatic()) { 1499 return null; 1500 } 1501 1502 JReferenceType enclosingType = x.getEnclosingType(); 1503 if (!typeOracle.checkClinit(currentMethod.getEnclosingType(), 1504 enclosingType)) { 1505 return null; 1506 } 1507 1508 while (!typeOracle.hasDirectClinit(enclosingType)) { 1511 enclosingType = enclosingType.extnds; 1512 } 1513 JMethod clinitMethod = (JMethod) enclosingType.methods.get(0); 1514 JsInvocation jsInvocation = new JsInvocation(); 1515 jsInvocation.setQualifier(getName(clinitMethod).makeRef()); 1516 return jsInvocation; 1517 } 1518 1519 private JsInvocation maybeCreateClinitCall(JMethod x) { 1520 if (!x.isStatic()) { 1521 return null; 1522 } 1523 JReferenceType enclosingType = x.getEnclosingType(); 1524 if (!typeOracle.hasClinit(enclosingType)) { 1525 return null; 1526 } 1527 if (program.isStaticImpl(x)) { 1528 return null; 1529 } 1530 if (x == enclosingType.methods.get(0)) { 1532 return null; 1533 } 1534 1535 while (!typeOracle.hasDirectClinit(enclosingType)) { 1538 enclosingType = enclosingType.extnds; 1539 } 1540 JMethod clinitMethod = (JMethod) enclosingType.methods.get(0); 1541 JsInvocation jsInvocation = new JsInvocation(); 1542 jsInvocation.setQualifier(getName(clinitMethod).makeRef()); 1543 return jsInvocation; 1544 } 1545 1546 private JsNode pop() { 1547 return (JsNode) nodeStack.pop(); 1548 } 1549 1550 privateList popList(int count) { 1551 JsNode[] array = new JsNode[count]; 1552 while (count > 0) { 1553 array[--count] = pop(); 1554 } 1555 1556 List list = new ArrayList (); 1557 for (int i = 0; i < array.length; i++) { 1558 JsNode item = array[i]; 1559 if (item != null) { 1560 list.add(item); 1561 } 1562 } 1563 return list; 1564 } 1565 1566 private void popList(JsCollection collection, int count) { 1567 JsNode[] array = new JsNode[count]; 1568 while (count > 0) { 1569 array[--count] = pop(); 1570 } 1571 1572 for (int i = 0; i < array.length; i++) { 1573 JsNode item = array[i]; 1574 if (item != null) { 1575 collection.addNode(item); 1576 } 1577 } 1578 } 1579 1580 private void push(JsNode node) { 1581 nodeStack.push(node); 1582 } 1583 } 1584 1585 private static class JavaToJsOperatorMap { 1586 private static final Map bOpMap = new IdentityHashMap (); 1587 private static final Map uOpMap = new IdentityHashMap (); 1588 1589 static { 1590 bOpMap.put(JBinaryOperator.MUL, JsBinaryOperator.MUL); 1591 bOpMap.put(JBinaryOperator.DIV, JsBinaryOperator.DIV); 1592 bOpMap.put(JBinaryOperator.MOD, JsBinaryOperator.MOD); 1593 bOpMap.put(JBinaryOperator.ADD, JsBinaryOperator.ADD); 1594 bOpMap.put(JBinaryOperator.SUB, JsBinaryOperator.SUB); 1595 bOpMap.put(JBinaryOperator.SHL, JsBinaryOperator.SHL); 1596 bOpMap.put(JBinaryOperator.SHR, JsBinaryOperator.SHR); 1597 bOpMap.put(JBinaryOperator.SHRU, JsBinaryOperator.SHRU); 1598 bOpMap.put(JBinaryOperator.LT, JsBinaryOperator.LT); 1599 bOpMap.put(JBinaryOperator.LTE, JsBinaryOperator.LTE); 1600 bOpMap.put(JBinaryOperator.GT, JsBinaryOperator.GT); 1601 bOpMap.put(JBinaryOperator.GTE, JsBinaryOperator.GTE); 1602 bOpMap.put(JBinaryOperator.EQ, JsBinaryOperator.EQ); 1603 bOpMap.put(JBinaryOperator.NEQ, JsBinaryOperator.NEQ); 1604 bOpMap.put(JBinaryOperator.BIT_AND, JsBinaryOperator.BIT_AND); 1605 bOpMap.put(JBinaryOperator.BIT_XOR, JsBinaryOperator.BIT_XOR); 1606 bOpMap.put(JBinaryOperator.BIT_OR, JsBinaryOperator.BIT_OR); 1607 bOpMap.put(JBinaryOperator.AND, JsBinaryOperator.AND); 1608 bOpMap.put(JBinaryOperator.OR, JsBinaryOperator.OR); 1609 bOpMap.put(JBinaryOperator.ASG, JsBinaryOperator.ASG); 1610 bOpMap.put(JBinaryOperator.ASG_ADD, JsBinaryOperator.ASG_ADD); 1611 bOpMap.put(JBinaryOperator.ASG_SUB, JsBinaryOperator.ASG_SUB); 1612 bOpMap.put(JBinaryOperator.ASG_MUL, JsBinaryOperator.ASG_MUL); 1613 bOpMap.put(JBinaryOperator.ASG_DIV, JsBinaryOperator.ASG_DIV); 1614 bOpMap.put(JBinaryOperator.ASG_MOD, JsBinaryOperator.ASG_MOD); 1615 bOpMap.put(JBinaryOperator.ASG_SHL, JsBinaryOperator.ASG_SHL); 1616 bOpMap.put(JBinaryOperator.ASG_SHR, JsBinaryOperator.ASG_SHR); 1617 bOpMap.put(JBinaryOperator.ASG_SHRU, JsBinaryOperator.ASG_SHRU); 1618 bOpMap.put(JBinaryOperator.ASG_BIT_AND, JsBinaryOperator.ASG_BIT_AND); 1619 bOpMap.put(JBinaryOperator.ASG_BIT_OR, JsBinaryOperator.ASG_BIT_OR); 1620 bOpMap.put(JBinaryOperator.ASG_BIT_XOR, JsBinaryOperator.ASG_BIT_XOR); 1621 1622 uOpMap.put(JUnaryOperator.INC, JsUnaryOperator.INC); 1623 uOpMap.put(JUnaryOperator.DEC, JsUnaryOperator.DEC); 1624 uOpMap.put(JUnaryOperator.NEG, JsUnaryOperator.NEG); 1625 uOpMap.put(JUnaryOperator.NOT, JsUnaryOperator.NOT); 1626 uOpMap.put(JUnaryOperator.BIT_NOT, JsUnaryOperator.BIT_NOT); 1627 } 1628 1629 public static JsBinaryOperator get(JBinaryOperator op) { 1630 return (JsBinaryOperator) bOpMap.get(op); 1631 } 1632 1633 public static JsUnaryOperator get(JUnaryOperator op) { 1634 return (JsUnaryOperator) uOpMap.get(op); 1635 } 1636 } 1637 1638 private class SortVisitor extends JVisitor { 1639 1640 private final HasNameSort hasNameSort = new HasNameSort(); 1641 1642 public void endVisit(JClassType x, Context ctx) { 1643 Collections.sort(x.fields, hasNameSort); 1644 1645 List methods = x.methods; 1647 Object a[] = methods.toArray(); 1648 Arrays.sort(a, 1, a.length, hasNameSort); 1649 for (int i = 1; i < a.length; i++) { 1650 methods.set(i, a[i]); 1651 } 1652 } 1653 1654 public void endVisit(JInterfaceType x, Context ctx) { 1655 Collections.sort(x.fields, hasNameSort); 1656 Collections.sort(x.methods, hasNameSort); 1657 } 1658 1659 public void endVisit(JMethod x, Context ctx) { 1660 Collections.sort(x.locals, hasNameSort); 1661 } 1662 1663 public void endVisit(JProgram x, Context ctx) { 1664 Collections.sort(x.entryMethods, hasNameSort); 1665 Collections.sort(x.getDeclaredTypes(), hasNameSort); 1666 } 1667 } 1668 1669 public static void exec(JProgram program, JsProgram jsProgram) { 1670 GenerateJavaScriptAST generateJavaScriptAST = new GenerateJavaScriptAST( 1671 program, jsProgram); 1672 generateJavaScriptAST.execImpl(); 1673 } 1674 1675 private static String getClassName(String fullName) { 1676 int pos = fullName.lastIndexOf("."); 1677 return fullName.substring(pos + 1); 1678 } 1679 1680 private static String getPackageName(String fullName) { 1681 int pos = fullName.lastIndexOf("."); 1682 return fullName.substring(0, pos + 1); 1683 } 1684 1685 private final Map catchMap = new IdentityHashMap (); 1686 private final Map classLits = new IdentityHashMap (); 1687 private final Map classScopes = new IdentityHashMap (); 1688 1689 1694 private final JsScope interfaceScope; 1695 1696 private final JsProgram jsProgram; 1697 private final Map methodMap = new IdentityHashMap (); 1698 private final Map names = new IdentityHashMap (); 1699 private JsName nullMethodName; 1700 1701 1705 private final JsScope objectScope; 1706 private final Map packageNames = new TreeMap (); 1707 private final Map polymorphicNames = new IdentityHashMap (); 1708 private final JProgram program; 1709 1710 1713 private final JsScope topScope; 1714 1715 private final JTypeOracle typeOracle; 1716 1717 private GenerateJavaScriptAST(JProgram program, JsProgram jsProgram) { 1718 this.program = program; 1719 typeOracle = program.typeOracle; 1720 this.jsProgram = jsProgram; 1721 topScope = jsProgram.getScope(); 1722 objectScope = jsProgram.getObjectScope(); 1723 interfaceScope = new JsScope(objectScope, "Interfaces"); 1724 } 1725 1726 String getNameString(HasName hasName) { 1727 String s = hasName.getName().replaceAll("_", "_1").replace('.', '_'); 1728 return s; 1729 } 1730 1731 String mangleName(JField x) { 1732 String s = getNameString(x.getEnclosingType()) + '_' + getNameString(x); 1733 return s; 1734 } 1735 1736 String mangleNameForGlobal(JMethod x) { 1737 String s = getNameString(x.getEnclosingType()) + '_' + getNameString(x) 1738 + "__"; 1739 for (int i = 0; i < x.getOriginalParamTypes().size(); ++i) { 1740 JType type = (JType) x.getOriginalParamTypes().get(i); 1741 s += type.getJavahSignatureName(); 1742 } 1743 return s; 1744 } 1745 1746 String mangleNameForPoly(JMethod x) { 1747 String s = getNameString(x) + "__"; 1748 for (int i = 0; i < x.getOriginalParamTypes().size(); ++i) { 1749 JType type = (JType) x.getOriginalParamTypes().get(i); 1750 s += type.getJavahSignatureName(); 1751 } 1752 return s; 1753 } 1754 1755 private void execImpl() { 1756 SortVisitor sorter = new SortVisitor(); 1757 sorter.accept(program); 1758 CreateNamesAndScopesVisitor creator = new CreateNamesAndScopesVisitor(); 1759 creator.accept(program); 1760 GenerateJavaScriptVisitor generator = new GenerateJavaScriptVisitor(); 1761 generator.accept(program); 1762 } 1763 1764 private JsName getName(HasName x) { 1765 return (JsName) names.get(x); 1766 } 1767 1768 private JsName getPolyName(HasName x) { 1769 return (JsName) polymorphicNames.get(x); 1770 } 1771 1772} 1773 | Popular Tags |