1 15 16 package javassist.compiler; 17 18 import javassist.*; 19 import javassist.bytecode.*; 20 import javassist.compiler.ast.*; 21 import java.util.ArrayList ; 22 23 25 public class MemberCodeGen extends CodeGen { 26 protected MemberResolver resolver; 27 protected CtClass thisClass; 28 protected MethodInfo thisMethod; 29 30 protected boolean resultStatic; 31 32 public MemberCodeGen(Bytecode b, CtClass cc, ClassPool cp) 33 { 34 super(b); 35 resolver = new MemberResolver(cp); 36 thisClass = cc; 37 thisMethod = null; 38 } 39 40 43 public void setThisMethod(CtMethod m) { 44 thisMethod = m.getMethodInfo2(); 45 if (typeChecker != null) 46 typeChecker.setThisMethod(thisMethod); 47 } 48 49 public CtClass getThisClass() { return thisClass; } 50 51 54 protected String getThisName() { 55 return MemberResolver.javaToJvmName(thisClass.getName()); 56 } 57 58 61 protected String getSuperName() throws CompileError { 62 return MemberResolver.javaToJvmName( 63 MemberResolver.getSuperclass(thisClass).getName()); 64 } 65 66 protected void insertDefaultSuperCall() throws CompileError { 67 bytecode.addAload(0); 68 bytecode.addInvokespecial(MemberResolver.getSuperclass(thisClass), 69 "<init>", "()V"); 70 } 71 72 static class JsrHook extends ReturnHook { 73 ArrayList jsrList; 74 int var; 75 76 JsrHook(CodeGen gen) { 77 super(gen); 78 jsrList = new ArrayList (); 79 var = gen.getMaxLocals(); 80 gen.incMaxLocals(1); 81 } 82 83 private void jsrJmp(Bytecode b) { 84 b.addOpcode(JSR); 85 jsrList.add(new Integer (b.currentPc())); 86 b.addIndex(0); 87 } 88 89 protected void doit(Bytecode b, int opcode) { 90 switch (opcode) { 91 case Opcode.RETURN : 92 jsrJmp(b); 93 break; 94 case ARETURN : 95 b.addAstore(var); 96 jsrJmp(b); 97 b.addAload(var); 98 break; 99 case IRETURN : 100 b.addIstore(var); 101 jsrJmp(b); 102 b.addIload(var); 103 break; 104 case LRETURN : 105 b.addLstore(var); 106 jsrJmp(b); 107 b.addLload(var); 108 break; 109 case DRETURN : 110 b.addDstore(var); 111 jsrJmp(b); 112 b.addDload(var); 113 break; 114 case FRETURN : 115 b.addFstore(var); 116 jsrJmp(b); 117 b.addFload(var); 118 break; 119 default : 120 throw new RuntimeException ("fatal"); 121 } 122 } 123 } 124 125 protected void atTryStmnt(Stmnt st) throws CompileError { 126 Bytecode bc = bytecode; 127 Stmnt body = (Stmnt)st.getLeft(); 128 if (body == null) 129 return; 130 131 ASTList catchList = (ASTList)st.getRight().getLeft(); 132 Stmnt finallyBlock = (Stmnt)st.getRight().getRight().getLeft(); 133 ArrayList gotoList = new ArrayList (); 134 135 JsrHook jsrHook = null; 136 if (finallyBlock != null) 137 jsrHook = new JsrHook(this); 138 139 int start = bc.currentPc(); 140 body.accept(this); 141 int end = bc.currentPc(); 142 if (start == end) 143 throw new CompileError("empty try block"); 144 145 boolean tryNotReturn = !hasReturned; 146 if (tryNotReturn) { 147 bc.addOpcode(Opcode.GOTO); 148 gotoList.add(new Integer (bc.currentPc())); 149 bc.addIndex(0); } 151 152 int var = getMaxLocals(); 153 incMaxLocals(1); 154 while (catchList != null) { 155 Pair p = (Pair)catchList.head(); 157 catchList = catchList.tail(); 158 Declarator decl = (Declarator)p.getLeft(); 159 Stmnt block = (Stmnt)p.getRight(); 160 161 decl.setLocalVar(var); 162 163 CtClass type = resolver.lookupClassByJvmName(decl.getClassName()); 164 decl.setClassName(MemberResolver.javaToJvmName(type.getName())); 165 bc.addExceptionHandler(start, end, bc.currentPc(), type); 166 bc.growStack(1); 167 bc.addAstore(var); 168 hasReturned = false; 169 if (block != null) 170 block.accept(this); 171 172 if (!hasReturned) { 173 bc.addOpcode(Opcode.GOTO); 174 gotoList.add(new Integer (bc.currentPc())); 175 bc.addIndex(0); tryNotReturn = true; 177 } 178 } 179 180 int pcFinally = -1; 181 if (finallyBlock != null) { 182 jsrHook.remove(this); 183 int pcAnyCatch = bc.currentPc(); 185 bc.addExceptionHandler(start, pcAnyCatch, pcAnyCatch, 0); 186 bc.growStack(1); 187 bc.addAstore(var); 188 bc.addOpcode(JSR); 189 int pcJsrIndex = bc.currentPc(); 190 bc.addIndex(0); bc.addAload(var); 192 bc.addOpcode(ATHROW); 193 194 pcFinally = bc.currentPc(); 196 bc.write16bit(pcJsrIndex, pcFinally - pcJsrIndex + 1); 197 int retAddr = getMaxLocals(); 198 incMaxLocals(1); 199 bc.growStack(1); bc.addAstore(retAddr); 201 hasReturned = false; 202 finallyBlock.accept(this); 203 if (!hasReturned) { 204 bc.addOpcode(RET); 205 bc.add(retAddr); 206 } 207 } 208 209 int pcEnd = bc.currentPc(); 210 patchGoto(gotoList, pcEnd); 211 if (finallyBlock != null) { 212 patchGoto(jsrHook.jsrList, pcFinally); 213 if (tryNotReturn) { 214 bc.addOpcode(JSR); 215 bc.addIndex(pcFinally - pcEnd); 216 } 217 } 218 219 hasReturned = !tryNotReturn; 220 } 221 222 public void atNewExpr(NewExpr expr) throws CompileError { 223 if (expr.isArray()) 224 atNewArrayExpr(expr); 225 else { 226 CtClass clazz = resolver.lookupClassByName(expr.getClassName()); 227 String cname = clazz.getName(); 228 ASTList args = expr.getArguments(); 229 bytecode.addNew(cname); 230 bytecode.addOpcode(DUP); 231 232 atMethodCallCore(clazz, MethodInfo.nameInit, args, 233 false, true, -1, null); 234 235 exprType = CLASS; 236 arrayDim = 0; 237 className = MemberResolver.javaToJvmName(cname); 238 } 239 } 240 241 public void atNewArrayExpr(NewExpr expr) throws CompileError { 242 if (expr.getInitializer() != null) 243 throw new CompileError("array initializer is not supported"); 244 245 int type = expr.getArrayType(); 246 ASTList size = expr.getArraySize(); 247 ASTList classname = expr.getClassName(); 248 if (size.length() > 1) { 249 atMultiNewArray(type, classname, size); 250 return; 251 } 252 253 size.head().accept(this); 254 exprType = type; 255 arrayDim = 1; 256 if (type == CLASS) { 257 className = resolveClassName(classname); 258 bytecode.addAnewarray(MemberResolver.jvmToJavaName(className)); 259 } 260 else { 261 className = null; 262 int atype = 0; 263 switch (type) { 264 case BOOLEAN : 265 atype = T_BOOLEAN; 266 break; 267 case CHAR : 268 atype = T_CHAR; 269 break; 270 case FLOAT : 271 atype = T_FLOAT; 272 break; 273 case DOUBLE : 274 atype = T_DOUBLE; 275 break; 276 case BYTE : 277 atype = T_BYTE; 278 break; 279 case SHORT : 280 atype = T_SHORT; 281 break; 282 case INT : 283 atype = T_INT; 284 break; 285 case LONG : 286 atype = T_LONG; 287 break; 288 default : 289 badNewExpr(); 290 break; 291 } 292 293 bytecode.addOpcode(NEWARRAY); 294 bytecode.add(atype); 295 } 296 } 297 298 private static void badNewExpr() throws CompileError { 299 throw new CompileError("bad new expression"); 300 } 301 302 protected void atMultiNewArray(int type, ASTList classname, ASTList size) 303 throws CompileError 304 { 305 int count, dim; 306 dim = size.length(); 307 for (count = 0; size != null; size = size.tail()) { 308 ASTree s = size.head(); 309 if (s == null) 310 break; 312 ++count; 313 s.accept(this); 314 if (exprType != INT) 315 throw new CompileError("bad type for array size"); 316 } 317 318 String desc; 319 exprType = type; 320 arrayDim = dim; 321 if (type == CLASS) { 322 className = resolveClassName(classname); 323 desc = toJvmArrayName(className, dim); 324 } 325 else 326 desc = toJvmTypeName(type, dim); 327 328 bytecode.addMultiNewarray(desc, count); 329 } 330 331 public void atCallExpr(CallExpr expr) throws CompileError { 332 String mname = null; 333 CtClass targetClass = null; 334 ASTree method = expr.oprand1(); 335 ASTList args = (ASTList)expr.oprand2(); 336 boolean isStatic = false; 337 boolean isSpecial = false; 338 int aload0pos = -1; 339 340 MemberResolver.Method cached = expr.getMethod(); 341 if (method instanceof Member) { 342 mname = ((Member)method).get(); 343 targetClass = thisClass; 344 if (inStaticMethod || (cached != null && cached.isStatic())) 345 isStatic = true; else { 347 aload0pos = bytecode.currentPc(); 348 bytecode.addAload(0); } 350 } 351 else if (method instanceof Keyword) { isSpecial = true; 353 mname = MethodInfo.nameInit; targetClass = thisClass; 355 if (inStaticMethod) 356 throw new CompileError("a constructor cannot be static"); 357 else 358 bytecode.addAload(0); 360 if (((Keyword)method).get() == SUPER) 361 targetClass = MemberResolver.getSuperclass(targetClass); 362 } 363 else if (method instanceof Expr) { 364 Expr e = (Expr)method; 365 mname = ((Symbol)e.oprand2()).get(); 366 int op = e.getOperator(); 367 if (op == MEMBER) { targetClass 369 = resolver.lookupClass(((Symbol)e.oprand1()).get(), false); 370 isStatic = true; 371 } 372 else if (op == '.') { 373 ASTree target = e.oprand1(); 374 if (target instanceof Keyword) 375 if (((Keyword)target).get() == SUPER) 376 isSpecial = true; 377 378 try { 379 target.accept(this); 380 } 381 catch (NoFieldException nfe) { 382 if (nfe.getExpr() != target) 383 throw nfe; 384 385 exprType = CLASS; 387 arrayDim = 0; 388 className = nfe.getField(); resolver.recordPackage(className); 390 isStatic = true; 391 } 392 393 if (arrayDim > 0) 394 targetClass = resolver.lookupClass(javaLangObject, true); 395 else if (exprType == CLASS ) 396 targetClass = resolver.lookupClassByJvmName(className); 397 else 398 badMethod(); 399 } 400 else 401 badMethod(); 402 } 403 else 404 fatal(); 405 406 atMethodCallCore(targetClass, mname, args, isStatic, isSpecial, 407 aload0pos, cached); 408 } 409 410 private static void badMethod() throws CompileError { 411 throw new CompileError("bad method"); 412 } 413 414 420 public void atMethodCallCore(CtClass targetClass, String mname, 421 ASTList args, boolean isStatic, boolean isSpecial, 422 int aload0pos, MemberResolver.Method found) 423 throws CompileError 424 { 425 int nargs = getMethodArgsLength(args); 426 int[] types = new int[nargs]; 427 int[] dims = new int[nargs]; 428 String [] cnames = new String [nargs]; 429 430 if (!isStatic && found != null && found.isStatic()) { 431 bytecode.addOpcode(POP); 432 isStatic = true; 433 } 434 435 int stack = bytecode.getStackDepth(); 436 437 atMethodArgs(args, types, dims, cnames); 439 440 int count = bytecode.getStackDepth() - stack + 1; 442 443 if (found == null) 444 found = resolver.lookupMethod(targetClass, thisMethod, mname, 445 types, dims, cnames, false); 446 447 if (found == null) { 448 String msg; 449 if (mname.equals(MethodInfo.nameInit)) 450 msg = "constructor not found"; 451 else 452 msg = "Method " + mname + " not found in " 453 + targetClass.getName(); 454 455 throw new CompileError(msg); 456 } 457 458 atMethodCallCore2(targetClass, mname, isStatic, isSpecial, 459 aload0pos, count, found); 460 } 461 462 private void atMethodCallCore2(CtClass targetClass, String mname, 463 boolean isStatic, boolean isSpecial, 464 int aload0pos, int count, 465 MemberResolver.Method found) 466 throws CompileError 467 { 468 CtClass declClass = found.declaring; 469 MethodInfo minfo = found.info; 470 String desc = minfo.getDescriptor(); 471 int acc = minfo.getAccessFlags(); 472 473 if (mname.equals(MethodInfo.nameInit)) { 474 isSpecial = true; 475 if (declClass != targetClass) 476 throw new CompileError("no such a constructor"); 477 478 if (declClass != thisClass && AccessFlag.isPrivate(acc)) { 479 desc = getAccessibleConstructor(desc, declClass, minfo); 480 bytecode.addOpcode(Opcode.ACONST_NULL); } 482 } 483 else if (AccessFlag.isPrivate(acc)) 484 if (declClass == thisClass) 485 isSpecial = true; 486 else { 487 isSpecial = false; 488 isStatic = true; 489 String origDesc = desc; 490 if ((acc & AccessFlag.STATIC) == 0) 491 desc = Descriptor.insertParameter(declClass.getName(), 492 origDesc); 493 494 acc = AccessFlag.setPackage(acc) | AccessFlag.STATIC; 495 mname = getAccessiblePrivate(mname, origDesc, desc, 496 minfo, declClass); 497 } 498 499 boolean popTarget = false; 500 if ((acc & AccessFlag.STATIC) != 0) { 501 if (!isStatic) { 502 507 isStatic = true; 508 if (aload0pos >= 0) 509 bytecode.write(aload0pos, NOP); 510 else 511 popTarget = true; 512 } 513 514 bytecode.addInvokestatic(declClass, mname, desc); 515 } 516 else if (isSpecial) bytecode.addInvokespecial(declClass, mname, desc); 518 else if (declClass.isInterface()) 519 bytecode.addInvokeinterface(declClass, mname, desc, count); 520 else 521 if (isStatic) 522 throw new CompileError(mname + " is not static"); 523 else 524 bytecode.addInvokevirtual(declClass, mname, desc); 525 526 setReturnType(desc, isStatic, popTarget); 527 } 528 529 536 protected String getAccessiblePrivate(String methodName, String desc, 537 String newDesc, MethodInfo minfo, 538 CtClass declClass) 539 throws CompileError 540 { 541 if (isEnclosing(declClass, thisClass)) { 542 AccessorMaker maker = declClass.getAccessorMaker(); 543 if (maker != null) 544 return maker.getMethodAccessor(methodName, desc, newDesc, 545 minfo); 546 } 547 548 throw new CompileError("Method " + methodName 549 + " is private"); 550 } 551 552 561 protected String getAccessibleConstructor(String desc, CtClass declClass, 562 MethodInfo minfo) 563 throws CompileError 564 { 565 if (isEnclosing(declClass, thisClass)) { 566 AccessorMaker maker = declClass.getAccessorMaker(); 567 if (maker != null) 568 return maker.getConstructor(declClass, desc, minfo); 569 } 570 571 throw new CompileError("the called constructor is private in " 572 + declClass.getName()); 573 } 574 575 private boolean isEnclosing(CtClass outer, CtClass inner) { 576 try { 577 while (inner != null) { 578 inner = inner.getDeclaringClass(); 579 if (inner == outer) 580 return true; 581 } 582 } 583 catch (NotFoundException e) {} 584 return false; 585 } 586 587 public int getMethodArgsLength(ASTList args) { 588 return ASTList.length(args); 589 } 590 591 public void atMethodArgs(ASTList args, int[] types, int[] dims, 592 String [] cnames) throws CompileError { 593 int i = 0; 594 while (args != null) { 595 ASTree a = args.head(); 596 a.accept(this); 597 types[i] = exprType; 598 dims[i] = arrayDim; 599 cnames[i] = className; 600 ++i; 601 args = args.tail(); 602 } 603 } 604 605 void setReturnType(String desc, boolean isStatic, boolean popTarget) 606 throws CompileError 607 { 608 int i = desc.indexOf(')'); 609 if (i < 0) 610 badMethod(); 611 612 char c = desc.charAt(++i); 613 int dim = 0; 614 while (c == '[') { 615 ++dim; 616 c = desc.charAt(++i); 617 } 618 619 arrayDim = dim; 620 if (c == 'L') { 621 int j = desc.indexOf(';', i + 1); 622 if (j < 0) 623 badMethod(); 624 625 exprType = CLASS; 626 className = desc.substring(i + 1, j); 627 } 628 else { 629 exprType = MemberResolver.descToType(c); 630 className = null; 631 } 632 633 int etype = exprType; 634 if (isStatic) { 635 if (popTarget) { 636 if (is2word(etype, dim)) { 637 bytecode.addOpcode(DUP2_X1); 638 bytecode.addOpcode(POP2); 639 bytecode.addOpcode(POP); 640 } 641 else if (etype == VOID) 642 bytecode.addOpcode(POP); 643 else { 644 bytecode.addOpcode(SWAP); 645 bytecode.addOpcode(POP); 646 } 647 } 648 } 649 } 650 651 protected void atFieldAssign(Expr expr, int op, ASTree left, 652 ASTree right, boolean doDup) throws CompileError 653 { 654 CtField f = fieldAccess(left); 655 boolean is_static = resultStatic; 656 if (op != '=' && !is_static) 657 bytecode.addOpcode(DUP); 658 659 int fi; 660 if (op == '=') { 661 FieldInfo finfo = f.getFieldInfo2(); 662 setFieldType(finfo); 663 AccessorMaker maker = isAccessibleField(f, finfo); 664 if (maker == null) 665 fi = addFieldrefInfo(f, finfo); 666 else 667 fi = 0; 668 } 669 else 670 fi = atFieldRead(f, is_static); 671 672 int fType = exprType; 673 int fDim = arrayDim; 674 String cname = className; 675 676 atAssignCore(expr, op, right, fType, fDim, cname); 677 678 boolean is2w = is2word(fType, fDim); 679 if (doDup) { 680 int dup_code; 681 if (is_static) 682 dup_code = (is2w ? DUP2 : DUP); 683 else 684 dup_code = (is2w ? DUP2_X1 : DUP_X1); 685 686 bytecode.addOpcode(dup_code); 687 } 688 689 atFieldAssignCore(f, is_static, fi, is2w); 690 691 exprType = fType; 692 arrayDim = fDim; 693 className = cname; 694 } 695 696 698 private void atFieldAssignCore(CtField f, boolean is_static, int fi, 699 boolean is2byte) throws CompileError { 700 if (fi != 0) { 701 if (is_static) { 702 bytecode.add(PUTSTATIC); 703 bytecode.growStack(is2byte ? -2 : -1); 704 } 705 else { 706 bytecode.add(PUTFIELD); 707 bytecode.growStack(is2byte ? -3 : -2); 708 } 709 710 bytecode.addIndex(fi); 711 } 712 else { 713 CtClass declClass = f.getDeclaringClass(); 714 AccessorMaker maker = declClass.getAccessorMaker(); 715 FieldInfo finfo = f.getFieldInfo2(); 717 MethodInfo minfo = maker.getFieldSetter(finfo, is_static); 718 bytecode.addInvokestatic(declClass, minfo.getName(), 719 minfo.getDescriptor()); 720 } 721 } 722 723 725 public void atMember(Member mem) throws CompileError { 726 atFieldRead(mem); 727 } 728 729 protected void atFieldRead(ASTree expr) throws CompileError 730 { 731 CtField f = fieldAccess(expr); 732 boolean is_static = resultStatic; 733 ASTree cexpr = TypeChecker.getConstantFieldValue(f); 734 if (cexpr == null) 735 atFieldRead(f, is_static); 736 else { 737 cexpr.accept(this); 738 setFieldType(f.getFieldInfo2()); 739 } 740 } 741 742 747 private int atFieldRead(CtField f, boolean isStatic) throws CompileError { 748 FieldInfo finfo = f.getFieldInfo2(); 749 boolean is2byte = setFieldType(finfo); 750 AccessorMaker maker = isAccessibleField(f, finfo); 751 if (maker != null) { 752 MethodInfo minfo = maker.getFieldGetter(finfo, isStatic); 753 bytecode.addInvokestatic(f.getDeclaringClass(), minfo.getName(), 754 minfo.getDescriptor()); 755 return 0; 756 } 757 else { 758 int fi = addFieldrefInfo(f, finfo); 759 if (isStatic) { 760 bytecode.add(GETSTATIC); 761 bytecode.growStack(is2byte ? 2 : 1); 762 } 763 else { 764 bytecode.add(GETFIELD); 765 bytecode.growStack(is2byte ? 1 : 0); 766 } 767 768 bytecode.addIndex(fi); 769 return fi; 770 } 771 } 772 773 778 private AccessorMaker isAccessibleField(CtField f, FieldInfo finfo) 779 throws CompileError 780 { 781 if (AccessFlag.isPrivate(finfo.getAccessFlags()) 782 && f.getDeclaringClass() != thisClass) { 783 CtClass declClass = f.getDeclaringClass(); 784 if (isEnclosing(declClass, thisClass)) { 785 AccessorMaker maker = declClass.getAccessorMaker(); 786 if (maker != null) 787 return maker; 788 else 789 throw new CompileError("fatal error. bug?"); 790 } 791 else 792 throw new CompileError("Field " + f.getName() + " in " 793 + declClass.getName() + " is private."); 794 } 795 796 return null; } 798 799 804 private boolean setFieldType(FieldInfo finfo) throws CompileError { 805 String type = finfo.getDescriptor(); 806 807 int i = 0; 808 int dim = 0; 809 char c = type.charAt(i); 810 while (c == '[') { 811 ++dim; 812 c = type.charAt(++i); 813 } 814 815 arrayDim = dim; 816 exprType = MemberResolver.descToType(c); 817 818 if (c == 'L') 819 className = type.substring(i + 1, type.indexOf(';', i + 1)); 820 else 821 className = null; 822 823 boolean is2byte = (c == 'J' || c == 'D'); 824 return is2byte; 825 } 826 827 private int addFieldrefInfo(CtField f, FieldInfo finfo) { 828 ConstPool cp = bytecode.getConstPool(); 829 String cname = f.getDeclaringClass().getName(); 830 int ci = cp.addClassInfo(cname); 831 String name = finfo.getName(); 832 String type = finfo.getDescriptor(); 833 return cp.addFieldrefInfo(ci, name, type); 834 } 835 836 protected void atFieldPlusPlus(int token, boolean isPost, 837 ASTree oprand, Expr expr, boolean doDup) 838 throws CompileError 839 { 840 CtField f = fieldAccess(oprand); 841 boolean is_static = resultStatic; 842 if (!is_static) 843 bytecode.addOpcode(DUP); 844 845 int fi = atFieldRead(f, is_static); 846 int t = exprType; 847 boolean is2w = is2word(t, arrayDim); 848 849 int dup_code; 850 if (is_static) 851 dup_code = (is2w ? DUP2 : DUP); 852 else 853 dup_code = (is2w ? DUP2_X1 : DUP_X1); 854 855 atPlusPlusCore(dup_code, doDup, token, isPost, expr); 856 atFieldAssignCore(f, is_static, fi, is2w); 857 } 858 859 861 protected CtField fieldAccess(ASTree expr) throws CompileError { 862 if (expr instanceof Member) { 863 String name = ((Member)expr).get(); 864 CtField f = null; 865 try { 866 f = thisClass.getField(name); 867 } 868 catch (NotFoundException e) { 869 throw new NoFieldException(name, expr); 871 } 872 873 boolean is_static = Modifier.isStatic(f.getModifiers()); 874 if (!is_static) 875 if (inStaticMethod) 876 throw new CompileError( 877 "not available in a static method: " + name); 878 else 879 bytecode.addAload(0); 881 resultStatic = is_static; 882 return f; 883 } 884 else if (expr instanceof Expr) { 885 Expr e = (Expr)expr; 886 int op = e.getOperator(); 887 if (op == MEMBER) { 888 892 CtField f = resolver.lookupField(((Symbol)e.oprand1()).get(), 893 (Symbol)e.oprand2()); 894 resultStatic = true; 895 return f; 896 } 897 else if (op == '.') { 898 CtField f = null; 899 try { 900 e.oprand1().accept(this); 901 905 if (exprType == CLASS && arrayDim == 0) 906 f = resolver.lookupFieldByJvmName(className, 907 (Symbol)e.oprand2()); 908 else 909 badLvalue(); 910 911 boolean is_static = Modifier.isStatic(f.getModifiers()); 912 if (is_static) 913 bytecode.addOpcode(POP); 914 915 resultStatic = is_static; 916 return f; 917 } 918 catch (NoFieldException nfe) { 919 if (nfe.getExpr() != e.oprand1()) 920 throw nfe; 921 922 926 Symbol fname = (Symbol)e.oprand2(); 927 String cname = nfe.getField(); 928 f = resolver.lookupFieldByJvmName2(cname, fname, expr); 929 resolver.recordPackage(cname); 930 resultStatic = true; 931 return f; 932 } 933 } 934 else 935 badLvalue(); 936 } 937 else 938 badLvalue(); 939 940 resultStatic = false; 941 return null; } 943 944 private static void badLvalue() throws CompileError { 945 throw new CompileError("bad l-value"); 946 } 947 948 public CtClass[] makeParamList(MethodDecl md) throws CompileError { 949 CtClass[] params; 950 ASTList plist = md.getParams(); 951 if (plist == null) 952 params = new CtClass[0]; 953 else { 954 int i = 0; 955 params = new CtClass[plist.length()]; 956 while (plist != null) { 957 params[i++] = resolver.lookupClass((Declarator)plist.head()); 958 plist = plist.tail(); 959 } 960 } 961 962 return params; 963 } 964 965 public CtClass[] makeThrowsList(MethodDecl md) throws CompileError { 966 CtClass[] clist; 967 ASTList list = md.getThrows(); 968 if (list == null) 969 return null; 970 else { 971 int i = 0; 972 clist = new CtClass[list.length()]; 973 while (list != null) { 974 clist[i++] = resolver.lookupClassByName((ASTList)list.head()); 975 list = list.tail(); 976 } 977 978 return clist; 979 } 980 } 981 982 987 protected String resolveClassName(ASTList name) throws CompileError { 988 return resolver.resolveClassName(name); 989 } 990 991 994 protected String resolveClassName(String jvmName) throws CompileError { 995 return resolver.resolveJvmClassName(jvmName); 996 } 997 } 998 | Popular Tags |