40 import com.sun.tools.javac.code.Type.*; |
40 import com.sun.tools.javac.code.Type.*; |
41 |
41 |
42 import com.sun.tools.javac.jvm.Target; |
42 import com.sun.tools.javac.jvm.Target; |
43 |
43 |
44 import static com.sun.tools.javac.code.Flags.*; |
44 import static com.sun.tools.javac.code.Flags.*; |
|
45 import static com.sun.tools.javac.code.Flags.BLOCK; |
45 import static com.sun.tools.javac.code.Kinds.*; |
46 import static com.sun.tools.javac.code.Kinds.*; |
46 import static com.sun.tools.javac.code.TypeTags.*; |
47 import static com.sun.tools.javac.code.TypeTags.*; |
47 import static com.sun.tools.javac.jvm.ByteCodes.*; |
48 import static com.sun.tools.javac.jvm.ByteCodes.*; |
|
49 import static com.sun.tools.javac.tree.JCTree.Tag.*; |
48 |
50 |
49 /** This pass translates away some syntactic sugar: inner classes, |
51 /** This pass translates away some syntactic sugar: inner classes, |
50 * class literals, assertions, foreach loops, etc. |
52 * class literals, assertions, foreach loops, etc. |
51 * |
53 * |
52 * <p><b>This is NOT part of any supported API. |
54 * <p><b>This is NOT part of any supported API. |
301 if (TreeInfo.name(tree.meth) == names._super) { |
303 if (TreeInfo.name(tree.meth) == names._super) { |
302 addFreeVars((ClassSymbol) TreeInfo.symbol(tree.meth).owner); |
304 addFreeVars((ClassSymbol) TreeInfo.symbol(tree.meth).owner); |
303 Symbol constructor = TreeInfo.symbol(tree.meth); |
305 Symbol constructor = TreeInfo.symbol(tree.meth); |
304 ClassSymbol c = (ClassSymbol)constructor.owner; |
306 ClassSymbol c = (ClassSymbol)constructor.owner; |
305 if (c.hasOuterInstance() && |
307 if (c.hasOuterInstance() && |
306 tree.meth.getTag() != JCTree.SELECT && |
308 !tree.meth.hasTag(SELECT) && |
307 outerThisStack.head != null) |
309 outerThisStack.head != null) |
308 visitSymbol(outerThisStack.head); |
310 visitSymbol(outerThisStack.head); |
309 } |
311 } |
310 super.visitApply(tree); |
312 super.visitApply(tree); |
311 } |
313 } |
506 |
508 |
507 /** Make an attributed unary expression. |
509 /** Make an attributed unary expression. |
508 * @param optag The operators tree tag. |
510 * @param optag The operators tree tag. |
509 * @param arg The operator's argument. |
511 * @param arg The operator's argument. |
510 */ |
512 */ |
511 JCUnary makeUnary(int optag, JCExpression arg) { |
513 JCUnary makeUnary(JCTree.Tag optag, JCExpression arg) { |
512 JCUnary tree = make.Unary(optag, arg); |
514 JCUnary tree = make.Unary(optag, arg); |
513 tree.operator = rs.resolveUnaryOperator( |
515 tree.operator = rs.resolveUnaryOperator( |
514 make_pos, optag, attrEnv, arg.type); |
516 make_pos, optag, attrEnv, arg.type); |
515 tree.type = tree.operator.type.getReturnType(); |
517 tree.type = tree.operator.type.getReturnType(); |
516 return tree; |
518 return tree; |
519 /** Make an attributed binary expression. |
521 /** Make an attributed binary expression. |
520 * @param optag The operators tree tag. |
522 * @param optag The operators tree tag. |
521 * @param lhs The operator's left argument. |
523 * @param lhs The operator's left argument. |
522 * @param rhs The operator's right argument. |
524 * @param rhs The operator's right argument. |
523 */ |
525 */ |
524 JCBinary makeBinary(int optag, JCExpression lhs, JCExpression rhs) { |
526 JCBinary makeBinary(JCTree.Tag optag, JCExpression lhs, JCExpression rhs) { |
525 JCBinary tree = make.Binary(optag, lhs, rhs); |
527 JCBinary tree = make.Binary(optag, lhs, rhs); |
526 tree.operator = rs.resolveBinaryOperator( |
528 tree.operator = rs.resolveBinaryOperator( |
527 make_pos, optag, attrEnv, lhs.type, rhs.type); |
529 make_pos, optag, attrEnv, lhs.type, rhs.type); |
528 tree.type = tree.operator.type.getReturnType(); |
530 tree.type = tree.operator.type.getReturnType(); |
529 return tree; |
531 return tree; |
532 /** Make an attributed assignop expression. |
534 /** Make an attributed assignop expression. |
533 * @param optag The operators tree tag. |
535 * @param optag The operators tree tag. |
534 * @param lhs The operator's left argument. |
536 * @param lhs The operator's left argument. |
535 * @param rhs The operator's right argument. |
537 * @param rhs The operator's right argument. |
536 */ |
538 */ |
537 JCAssignOp makeAssignop(int optag, JCTree lhs, JCTree rhs) { |
539 JCAssignOp makeAssignop(JCTree.Tag optag, JCTree lhs, JCTree rhs) { |
538 JCAssignOp tree = make.Assignop(optag, lhs, rhs); |
540 JCAssignOp tree = make.Assignop(optag, lhs, rhs); |
539 tree.operator = rs.resolveBinaryOperator( |
541 tree.operator = rs.resolveBinaryOperator( |
540 make_pos, tree.getTag() - JCTree.ASGOffset, attrEnv, lhs.type, rhs.type); |
542 make_pos, tree.getTag().noAssignOp(), attrEnv, lhs.type, rhs.type); |
541 tree.type = lhs.type; |
543 tree.type = lhs.type; |
542 return tree; |
544 return tree; |
543 } |
545 } |
544 |
546 |
545 /** Convert tree into string object, unless it has already a |
547 /** Convert tree into string object, unless it has already a |
800 * null if tree is not a subtree of an operation. |
802 * null if tree is not a subtree of an operation. |
801 */ |
803 */ |
802 private static int accessCode(JCTree tree, JCTree enclOp) { |
804 private static int accessCode(JCTree tree, JCTree enclOp) { |
803 if (enclOp == null) |
805 if (enclOp == null) |
804 return DEREFcode; |
806 return DEREFcode; |
805 else if (enclOp.getTag() == JCTree.ASSIGN && |
807 else if (enclOp.hasTag(ASSIGN) && |
806 tree == TreeInfo.skipParens(((JCAssign) enclOp).lhs)) |
808 tree == TreeInfo.skipParens(((JCAssign) enclOp).lhs)) |
807 return ASSIGNcode; |
809 return ASSIGNcode; |
808 else if (JCTree.PREINC <= enclOp.getTag() && enclOp.getTag() <= JCTree.POSTDEC && |
810 else if (enclOp.getTag().isIncOrDecUnaryOp() && |
809 tree == TreeInfo.skipParens(((JCUnary) enclOp).arg)) |
811 tree == TreeInfo.skipParens(((JCUnary) enclOp).arg)) |
810 return (enclOp.getTag() - JCTree.PREINC) * 2 + PREINCcode; |
812 return mapTagToUnaryOpCode(enclOp.getTag()); |
811 else if (JCTree.BITOR_ASG <= enclOp.getTag() && enclOp.getTag() <= JCTree.MOD_ASG && |
813 else if (enclOp.getTag().isAssignop() && |
812 tree == TreeInfo.skipParens(((JCAssignOp) enclOp).lhs)) |
814 tree == TreeInfo.skipParens(((JCAssignOp) enclOp).lhs)) |
813 return accessCode(((OperatorSymbol) ((JCAssignOp) enclOp).operator).opcode); |
815 return accessCode(((OperatorSymbol) ((JCAssignOp) enclOp).operator).opcode); |
814 else |
816 else |
815 return DEREFcode; |
817 return DEREFcode; |
816 } |
818 } |
830 } |
832 } |
831 |
833 |
832 /** Return tree tag for assignment operation corresponding |
834 /** Return tree tag for assignment operation corresponding |
833 * to given binary operator. |
835 * to given binary operator. |
834 */ |
836 */ |
835 private static int treeTag(OperatorSymbol operator) { |
837 private static JCTree.Tag treeTag(OperatorSymbol operator) { |
836 switch (operator.opcode) { |
838 switch (operator.opcode) { |
837 case ByteCodes.ior: case ByteCodes.lor: |
839 case ByteCodes.ior: case ByteCodes.lor: |
838 return JCTree.BITOR_ASG; |
840 return BITOR_ASG; |
839 case ByteCodes.ixor: case ByteCodes.lxor: |
841 case ByteCodes.ixor: case ByteCodes.lxor: |
840 return JCTree.BITXOR_ASG; |
842 return BITXOR_ASG; |
841 case ByteCodes.iand: case ByteCodes.land: |
843 case ByteCodes.iand: case ByteCodes.land: |
842 return JCTree.BITAND_ASG; |
844 return BITAND_ASG; |
843 case ByteCodes.ishl: case ByteCodes.lshl: |
845 case ByteCodes.ishl: case ByteCodes.lshl: |
844 case ByteCodes.ishll: case ByteCodes.lshll: |
846 case ByteCodes.ishll: case ByteCodes.lshll: |
845 return JCTree.SL_ASG; |
847 return SL_ASG; |
846 case ByteCodes.ishr: case ByteCodes.lshr: |
848 case ByteCodes.ishr: case ByteCodes.lshr: |
847 case ByteCodes.ishrl: case ByteCodes.lshrl: |
849 case ByteCodes.ishrl: case ByteCodes.lshrl: |
848 return JCTree.SR_ASG; |
850 return SR_ASG; |
849 case ByteCodes.iushr: case ByteCodes.lushr: |
851 case ByteCodes.iushr: case ByteCodes.lushr: |
850 case ByteCodes.iushrl: case ByteCodes.lushrl: |
852 case ByteCodes.iushrl: case ByteCodes.lushrl: |
851 return JCTree.USR_ASG; |
853 return USR_ASG; |
852 case ByteCodes.iadd: case ByteCodes.ladd: |
854 case ByteCodes.iadd: case ByteCodes.ladd: |
853 case ByteCodes.fadd: case ByteCodes.dadd: |
855 case ByteCodes.fadd: case ByteCodes.dadd: |
854 case ByteCodes.string_add: |
856 case ByteCodes.string_add: |
855 return JCTree.PLUS_ASG; |
857 return PLUS_ASG; |
856 case ByteCodes.isub: case ByteCodes.lsub: |
858 case ByteCodes.isub: case ByteCodes.lsub: |
857 case ByteCodes.fsub: case ByteCodes.dsub: |
859 case ByteCodes.fsub: case ByteCodes.dsub: |
858 return JCTree.MINUS_ASG; |
860 return MINUS_ASG; |
859 case ByteCodes.imul: case ByteCodes.lmul: |
861 case ByteCodes.imul: case ByteCodes.lmul: |
860 case ByteCodes.fmul: case ByteCodes.dmul: |
862 case ByteCodes.fmul: case ByteCodes.dmul: |
861 return JCTree.MUL_ASG; |
863 return MUL_ASG; |
862 case ByteCodes.idiv: case ByteCodes.ldiv: |
864 case ByteCodes.idiv: case ByteCodes.ldiv: |
863 case ByteCodes.fdiv: case ByteCodes.ddiv: |
865 case ByteCodes.fdiv: case ByteCodes.ddiv: |
864 return JCTree.DIV_ASG; |
866 return DIV_ASG; |
865 case ByteCodes.imod: case ByteCodes.lmod: |
867 case ByteCodes.imod: case ByteCodes.lmod: |
866 case ByteCodes.fmod: case ByteCodes.dmod: |
868 case ByteCodes.fmod: case ByteCodes.dmod: |
867 return JCTree.MOD_ASG; |
869 return MOD_ASG; |
868 default: |
870 default: |
869 throw new AssertionError(); |
871 throw new AssertionError(); |
870 } |
872 } |
871 } |
873 } |
872 |
874 |
1001 sym.packge() == currentClass.packge()) |
1003 sym.packge() == currentClass.packge()) |
1002 return false; |
1004 return false; |
1003 if (!currentClass.isSubClass(sym.owner, types)) |
1005 if (!currentClass.isSubClass(sym.owner, types)) |
1004 return true; |
1006 return true; |
1005 if ((sym.flags() & STATIC) != 0 || |
1007 if ((sym.flags() & STATIC) != 0 || |
1006 tree.getTag() != JCTree.SELECT || |
1008 !tree.hasTag(SELECT) || |
1007 TreeInfo.name(((JCFieldAccess) tree).selected) == names._super) |
1009 TreeInfo.name(((JCFieldAccess) tree).selected) == names._super) |
1008 return false; |
1010 return false; |
1009 return !((JCFieldAccess) tree).selected.type.tsym.isSubClass(currentClass, types); |
1011 return !((JCFieldAccess) tree).selected.type.tsym.isSubClass(currentClass, types); |
1010 } |
1012 } |
1011 |
1013 |
1016 */ |
1018 */ |
1017 ClassSymbol accessClass(Symbol sym, boolean protAccess, JCTree tree) { |
1019 ClassSymbol accessClass(Symbol sym, boolean protAccess, JCTree tree) { |
1018 if (protAccess) { |
1020 if (protAccess) { |
1019 Symbol qualifier = null; |
1021 Symbol qualifier = null; |
1020 ClassSymbol c = currentClass; |
1022 ClassSymbol c = currentClass; |
1021 if (tree.getTag() == JCTree.SELECT && (sym.flags() & STATIC) == 0) { |
1023 if (tree.hasTag(SELECT) && (sym.flags() & STATIC) == 0) { |
1022 qualifier = ((JCFieldAccess) tree).selected.type.tsym; |
1024 qualifier = ((JCFieldAccess) tree).selected.type.tsym; |
1023 while (!qualifier.isSubClass(c, types)) { |
1025 while (!qualifier.isSubClass(c, types)) { |
1024 c = c.owner.enclClass(); |
1026 c = c.owner.enclClass(); |
1025 } |
1027 } |
1026 return c; |
1028 return c; |
1056 // Otherwise replace the variable by its proxy. |
1058 // Otherwise replace the variable by its proxy. |
1057 sym = proxies.lookup(proxyName(sym.name)).sym; |
1059 sym = proxies.lookup(proxyName(sym.name)).sym; |
1058 Assert.check(sym != null && (sym.flags_field & FINAL) != 0); |
1060 Assert.check(sym != null && (sym.flags_field & FINAL) != 0); |
1059 tree = make.at(tree.pos).Ident(sym); |
1061 tree = make.at(tree.pos).Ident(sym); |
1060 } |
1062 } |
1061 JCExpression base = (tree.getTag() == JCTree.SELECT) ? ((JCFieldAccess) tree).selected : null; |
1063 JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) tree).selected : null; |
1062 switch (sym.kind) { |
1064 switch (sym.kind) { |
1063 case TYP: |
1065 case TYP: |
1064 if (sym.owner.kind != PCK) { |
1066 if (sym.owner.kind != PCK) { |
1065 // Convert type idents to |
1067 // Convert type idents to |
1066 // <flat name> or <package name> . <flat name> |
1068 // <flat name> or <package name> . <flat name> |
1067 Name flatname = Convert.shortName(sym.flatName()); |
1069 Name flatname = Convert.shortName(sym.flatName()); |
1068 while (base != null && |
1070 while (base != null && |
1069 TreeInfo.symbol(base) != null && |
1071 TreeInfo.symbol(base) != null && |
1070 TreeInfo.symbol(base).kind != PCK) { |
1072 TreeInfo.symbol(base).kind != PCK) { |
1071 base = (base.getTag() == JCTree.SELECT) |
1073 base = (base.hasTag(SELECT)) |
1072 ? ((JCFieldAccess) base).selected |
1074 ? ((JCFieldAccess) base).selected |
1073 : null; |
1075 : null; |
1074 } |
1076 } |
1075 if (tree.getTag() == JCTree.IDENT) { |
1077 if (tree.hasTag(IDENT)) { |
1076 ((JCIdent) tree).name = flatname; |
1078 ((JCIdent) tree).name = flatname; |
1077 } else if (base == null) { |
1079 } else if (base == null) { |
1078 tree = make.at(tree.pos).Ident(sym); |
1080 tree = make.at(tree.pos).Ident(sym); |
1079 ((JCIdent) tree).name = flatname; |
1081 ((JCIdent) tree).name = flatname; |
1080 } else { |
1082 } else { |
1218 accessDef(cdef.pos, sym, accessors[i], i)); |
1220 accessDef(cdef.pos, sym, accessors[i], i)); |
1219 } |
1221 } |
1220 } |
1222 } |
1221 } |
1223 } |
1222 |
1224 |
|
1225 /** Maps unary operator integer codes to JCTree.Tag objects |
|
1226 * @param unaryOpCode the unary operator code |
|
1227 */ |
|
1228 private static Tag mapUnaryOpCodeToTag(int unaryOpCode){ |
|
1229 switch (unaryOpCode){ |
|
1230 case PREINCcode: |
|
1231 return PREINC; |
|
1232 case PREDECcode: |
|
1233 return PREDEC; |
|
1234 case POSTINCcode: |
|
1235 return POSTINC; |
|
1236 case POSTDECcode: |
|
1237 return POSTDEC; |
|
1238 default: |
|
1239 return NO_TAG; |
|
1240 } |
|
1241 } |
|
1242 |
|
1243 /** Maps JCTree.Tag objects to unary operator integer codes |
|
1244 * @param tag the JCTree.Tag |
|
1245 */ |
|
1246 private static int mapTagToUnaryOpCode(Tag tag){ |
|
1247 switch (tag){ |
|
1248 case PREINC: |
|
1249 return PREINCcode; |
|
1250 case PREDEC: |
|
1251 return PREDECcode; |
|
1252 case POSTINC: |
|
1253 return POSTINCcode; |
|
1254 case POSTDEC: |
|
1255 return POSTDECcode; |
|
1256 default: |
|
1257 return -1; |
|
1258 } |
|
1259 } |
|
1260 |
1223 /** Construct definition of an access method. |
1261 /** Construct definition of an access method. |
1224 * @param pos The source code position of the definition. |
1262 * @param pos The source code position of the definition. |
1225 * @param vsym The private or protected symbol. |
1263 * @param vsym The private or protected symbol. |
1226 * @param accessor The access method for the symbol. |
1264 * @param accessor The access method for the symbol. |
1227 * @param acode The access code. |
1265 * @param acode The access code. |
1257 break; |
1295 break; |
1258 case ASSIGNcode: |
1296 case ASSIGNcode: |
1259 expr = make.Assign(ref, args.head); |
1297 expr = make.Assign(ref, args.head); |
1260 break; |
1298 break; |
1261 case PREINCcode: case POSTINCcode: case PREDECcode: case POSTDECcode: |
1299 case PREINCcode: case POSTINCcode: case PREDECcode: case POSTDECcode: |
1262 expr = makeUnary( |
1300 expr = makeUnary(mapUnaryOpCodeToTag(acode1), ref); |
1263 ((acode1 - PREINCcode) >> 1) + JCTree.PREINC, ref); |
|
1264 break; |
1301 break; |
1265 default: |
1302 default: |
1266 expr = make.Assignop( |
1303 expr = make.Assignop( |
1267 treeTag(binaryAccessOperator(acode1)), ref, args.head); |
1304 treeTag(binaryAccessOperator(acode1)), ref, args.head); |
1268 ((JCAssignOp) expr).operator = binaryAccessOperator(acode1); |
1305 ((JCAssignOp) expr).operator = binaryAccessOperator(acode1); |
1574 List.<JCExpression>nil()); |
1611 List.<JCExpression>nil()); |
1575 return make.Exec(resourceClose); |
1612 return make.Exec(resourceClose); |
1576 } |
1613 } |
1577 |
1614 |
1578 private JCExpression makeNonNullCheck(JCExpression expression) { |
1615 private JCExpression makeNonNullCheck(JCExpression expression) { |
1579 return makeBinary(JCTree.NE, expression, makeNull()); |
1616 return makeBinary(NE, expression, makeNull()); |
1580 } |
1617 } |
1581 |
1618 |
1582 /** Construct a tree that represents the outer instance |
1619 /** Construct a tree that represents the outer instance |
1583 * <C.this>. Never pick the current `this'. |
1620 * <C.this>. Never pick the current `this'. |
1584 * @param pos The source code position to be used for the tree. |
1621 * @param pos The source code position to be used for the tree. |
1806 syms.classLoaderType)); |
1843 syms.classLoaderType)); |
1807 // clvalue := "(cl$ == null) ? |
1844 // clvalue := "(cl$ == null) ? |
1808 // $newcache.getClass().getComponentType().getClassLoader() : cl$" |
1845 // $newcache.getClass().getComponentType().getClassLoader() : cl$" |
1809 JCExpression clvalue = |
1846 JCExpression clvalue = |
1810 make.Conditional( |
1847 make.Conditional( |
1811 makeBinary(JCTree.EQ, make.Ident(clsym), makeNull()), |
1848 makeBinary(EQ, make.Ident(clsym), makeNull()), |
1812 make.Assign( |
1849 make.Assign( |
1813 make.Ident(clsym), |
1850 make.Ident(clsym), |
1814 makeCall( |
1851 makeCall( |
1815 makeCall(makeCall(newcache, |
1852 makeCall(makeCall(newcache, |
1816 names.getClass, |
1853 names.getClass, |
1974 // - <cache> is the cache variable for tsig. |
2011 // - <cache> is the cache variable for tsig. |
1975 String sig = |
2012 String sig = |
1976 writer.xClassName(type).toString().replace('/', '.'); |
2013 writer.xClassName(type).toString().replace('/', '.'); |
1977 Symbol cs = cacheSym(pos, sig); |
2014 Symbol cs = cacheSym(pos, sig); |
1978 return make_at(pos).Conditional( |
2015 return make_at(pos).Conditional( |
1979 makeBinary(JCTree.EQ, make.Ident(cs), makeNull()), |
2016 makeBinary(EQ, make.Ident(cs), makeNull()), |
1980 make.Assign( |
2017 make.Assign( |
1981 make.Ident(cs), |
2018 make.Ident(cs), |
1982 make.App( |
2019 make.App( |
1983 make.Ident(classDollarSym(pos)), |
2020 make.Ident(classDollarSym(pos)), |
1984 List.<JCExpression>of(make.Literal(CLASS, sig) |
2021 List.<JCExpression>of(make.Literal(CLASS, sig) |
2021 names.desiredAssertionStatus, |
2058 names.desiredAssertionStatus, |
2022 types.erasure(syms.classType), |
2059 types.erasure(syms.classType), |
2023 List.<Type>nil()); |
2060 List.<Type>nil()); |
2024 JCClassDecl containerDef = classDef(container); |
2061 JCClassDecl containerDef = classDef(container); |
2025 make_at(containerDef.pos()); |
2062 make_at(containerDef.pos()); |
2026 JCExpression notStatus = makeUnary(JCTree.NOT, make.App(make.Select( |
2063 JCExpression notStatus = makeUnary(NOT, make.App(make.Select( |
2027 classOfType(types.erasure(outermostClass.type), |
2064 classOfType(types.erasure(outermostClass.type), |
2028 containerDef.pos()), |
2065 containerDef.pos()), |
2029 desiredAssertionStatusSym))); |
2066 desiredAssertionStatusSym))); |
2030 JCVariableDecl assertDisabledDef = make.VarDef(assertDisabledSym, |
2067 JCVariableDecl assertDisabledDef = make.VarDef(assertDisabledSym, |
2031 notStatus); |
2068 notStatus); |
2032 containerDef.defs = containerDef.defs.prepend(assertDisabledDef); |
2069 containerDef.defs = containerDef.defs.prepend(assertDisabledDef); |
2033 } |
2070 } |
2034 make_at(pos); |
2071 make_at(pos); |
2035 return makeUnary(JCTree.NOT, make.Ident(assertDisabledSym)); |
2072 return makeUnary(NOT, make.Ident(assertDisabledSym)); |
2036 } |
2073 } |
2037 |
2074 |
2038 |
2075 |
2039 /************************************************************************** |
2076 /************************************************************************** |
2040 * Building blocks for let expressions |
2077 * Building blocks for let expressions |
2060 * in the let expression. |
2097 * in the let expression. |
2061 */ |
2098 */ |
2062 JCTree abstractRval(JCTree rval, Type type, TreeBuilder builder) { |
2099 JCTree abstractRval(JCTree rval, Type type, TreeBuilder builder) { |
2063 rval = TreeInfo.skipParens(rval); |
2100 rval = TreeInfo.skipParens(rval); |
2064 switch (rval.getTag()) { |
2101 switch (rval.getTag()) { |
2065 case JCTree.LITERAL: |
2102 case LITERAL: |
2066 return builder.build(rval); |
2103 return builder.build(rval); |
2067 case JCTree.IDENT: |
2104 case IDENT: |
2068 JCIdent id = (JCIdent) rval; |
2105 JCIdent id = (JCIdent) rval; |
2069 if ((id.sym.flags() & FINAL) != 0 && id.sym.owner.kind == MTH) |
2106 if ((id.sym.flags() & FINAL) != 0 && id.sym.owner.kind == MTH) |
2070 return builder.build(rval); |
2107 return builder.build(rval); |
2071 } |
2108 } |
2072 VarSymbol var = |
2109 VarSymbol var = |
2095 // select in a temporary, and for Indexed expressions, where we |
2132 // select in a temporary, and for Indexed expressions, where we |
2096 // place both the indexed expression and the index value in temps. |
2133 // place both the indexed expression and the index value in temps. |
2097 JCTree abstractLval(JCTree lval, final TreeBuilder builder) { |
2134 JCTree abstractLval(JCTree lval, final TreeBuilder builder) { |
2098 lval = TreeInfo.skipParens(lval); |
2135 lval = TreeInfo.skipParens(lval); |
2099 switch (lval.getTag()) { |
2136 switch (lval.getTag()) { |
2100 case JCTree.IDENT: |
2137 case IDENT: |
2101 return builder.build(lval); |
2138 return builder.build(lval); |
2102 case JCTree.SELECT: { |
2139 case SELECT: { |
2103 final JCFieldAccess s = (JCFieldAccess)lval; |
2140 final JCFieldAccess s = (JCFieldAccess)lval; |
2104 JCTree selected = TreeInfo.skipParens(s.selected); |
2141 JCTree selected = TreeInfo.skipParens(s.selected); |
2105 Symbol lid = TreeInfo.symbol(s.selected); |
2142 Symbol lid = TreeInfo.symbol(s.selected); |
2106 if (lid != null && lid.kind == TYP) return builder.build(lval); |
2143 if (lid != null && lid.kind == TYP) return builder.build(lval); |
2107 return abstractRval(s.selected, new TreeBuilder() { |
2144 return abstractRval(s.selected, new TreeBuilder() { |
2108 public JCTree build(final JCTree selected) { |
2145 public JCTree build(final JCTree selected) { |
2109 return builder.build(make.Select((JCExpression)selected, s.sym)); |
2146 return builder.build(make.Select((JCExpression)selected, s.sym)); |
2110 } |
2147 } |
2111 }); |
2148 }); |
2112 } |
2149 } |
2113 case JCTree.INDEXED: { |
2150 case INDEXED: { |
2114 final JCArrayAccess i = (JCArrayAccess)lval; |
2151 final JCArrayAccess i = (JCArrayAccess)lval; |
2115 return abstractRval(i.indexed, new TreeBuilder() { |
2152 return abstractRval(i.indexed, new TreeBuilder() { |
2116 public JCTree build(final JCTree indexed) { |
2153 public JCTree build(final JCTree indexed) { |
2117 return abstractRval(i.index, syms.intType, new TreeBuilder() { |
2154 return abstractRval(i.index, syms.intType, new TreeBuilder() { |
2118 public JCTree build(final JCTree index) { |
2155 public JCTree build(final JCTree index) { |
2343 ListBuffer<JCTree> enumDefs = new ListBuffer<JCTree>(); |
2380 ListBuffer<JCTree> enumDefs = new ListBuffer<JCTree>(); |
2344 ListBuffer<JCTree> otherDefs = new ListBuffer<JCTree>(); |
2381 ListBuffer<JCTree> otherDefs = new ListBuffer<JCTree>(); |
2345 for (List<JCTree> defs = tree.defs; |
2382 for (List<JCTree> defs = tree.defs; |
2346 defs.nonEmpty(); |
2383 defs.nonEmpty(); |
2347 defs=defs.tail) { |
2384 defs=defs.tail) { |
2348 if (defs.head.getTag() == JCTree.VARDEF && (((JCVariableDecl) defs.head).mods.flags & ENUM) != 0) { |
2385 if (defs.head.hasTag(VARDEF) && (((JCVariableDecl) defs.head).mods.flags & ENUM) != 0) { |
2349 JCVariableDecl var = (JCVariableDecl)defs.head; |
2386 JCVariableDecl var = (JCVariableDecl)defs.head; |
2350 visitEnumConstantDef(var, nextOrdinal++); |
2387 visitEnumConstantDef(var, nextOrdinal++); |
2351 values.append(make.QualIdent(var.sym)); |
2388 values.append(make.QualIdent(var.sym)); |
2352 enumDefs.append(var); |
2389 enumDefs.append(var); |
2353 } else { |
2390 } else { |
2755 JCExpression cond = assertFlagTest(tree.pos()); |
2792 JCExpression cond = assertFlagTest(tree.pos()); |
2756 List<JCExpression> exnArgs = (tree.detail == null) ? |
2793 List<JCExpression> exnArgs = (tree.detail == null) ? |
2757 List.<JCExpression>nil() : List.of(translate(tree.detail)); |
2794 List.<JCExpression>nil() : List.of(translate(tree.detail)); |
2758 if (!tree.cond.type.isFalse()) { |
2795 if (!tree.cond.type.isFalse()) { |
2759 cond = makeBinary |
2796 cond = makeBinary |
2760 (JCTree.AND, |
2797 (AND, |
2761 cond, |
2798 cond, |
2762 makeUnary(JCTree.NOT, tree.cond)); |
2799 makeUnary(NOT, tree.cond)); |
2763 } |
2800 } |
2764 result = |
2801 result = |
2765 make.If(cond, |
2802 make.If(cond, |
2766 make_at(detailPos). |
2803 make_at(detailPos). |
2767 Throw(makeNewClass(syms.assertionErrorType, exnArgs)), |
2804 Throw(makeNewClass(syms.assertionErrorType, exnArgs)), |
2814 // the explicit constructor arguments. If the call |
2851 // the explicit constructor arguments. If the call |
2815 // is not qualified, pass the correct outer instance as |
2852 // is not qualified, pass the correct outer instance as |
2816 // first argument. |
2853 // first argument. |
2817 if (c.hasOuterInstance()) { |
2854 if (c.hasOuterInstance()) { |
2818 JCExpression thisArg; |
2855 JCExpression thisArg; |
2819 if (tree.meth.getTag() == JCTree.SELECT) { |
2856 if (tree.meth.hasTag(SELECT)) { |
2820 thisArg = attr. |
2857 thisArg = attr. |
2821 makeNullCheck(translate(((JCFieldAccess) tree.meth).selected)); |
2858 makeNullCheck(translate(((JCFieldAccess) tree.meth).selected)); |
2822 tree.meth = make.Ident(constructor); |
2859 tree.meth = make.Ident(constructor); |
2823 ((JCIdent) tree.meth).name = methName; |
2860 ((JCIdent) tree.meth).name = methName; |
2824 } else if ((c.owner.kind & (MTH | VAR)) != 0 || methName == names._this){ |
2861 } else if ((c.owner.kind & (MTH | VAR)) != 0 || methName == names._this){ |
2835 tree.meth = translate(tree.meth); |
2872 tree.meth = translate(tree.meth); |
2836 |
2873 |
2837 // If the translated method itself is an Apply tree, we are |
2874 // If the translated method itself is an Apply tree, we are |
2838 // seeing an access method invocation. In this case, append |
2875 // seeing an access method invocation. In this case, append |
2839 // the method arguments to the arguments of the access method. |
2876 // the method arguments to the arguments of the access method. |
2840 if (tree.meth.getTag() == JCTree.APPLY) { |
2877 if (tree.meth.hasTag(APPLY)) { |
2841 JCMethodInvocation app = (JCMethodInvocation)tree.meth; |
2878 JCMethodInvocation app = (JCMethodInvocation)tree.meth; |
2842 app.args = tree.args.prependList(app.args); |
2879 app.args = tree.args.prependList(app.args); |
2843 result = app; |
2880 result = app; |
2844 return; |
2881 return; |
2845 } |
2882 } |
2969 tree.rhs = translate(tree.rhs, tree.lhs.type); |
3006 tree.rhs = translate(tree.rhs, tree.lhs.type); |
2970 |
3007 |
2971 // If translated left hand side is an Apply, we are |
3008 // If translated left hand side is an Apply, we are |
2972 // seeing an access method invocation. In this case, append |
3009 // seeing an access method invocation. In this case, append |
2973 // right hand side as last argument of the access method. |
3010 // right hand side as last argument of the access method. |
2974 if (tree.lhs.getTag() == JCTree.APPLY) { |
3011 if (tree.lhs.hasTag(APPLY)) { |
2975 JCMethodInvocation app = (JCMethodInvocation)tree.lhs; |
3012 JCMethodInvocation app = (JCMethodInvocation)tree.lhs; |
2976 app.args = List.of(tree.rhs).prependList(app.args); |
3013 app.args = List.of(tree.rhs).prependList(app.args); |
2977 result = app; |
3014 result = app; |
2978 } else { |
3015 } else { |
2979 result = tree; |
3016 result = tree; |
2986 // boxing required; need to rewrite as x = (unbox typeof x)(x op y); |
3023 // boxing required; need to rewrite as x = (unbox typeof x)(x op y); |
2987 // or if x == (typeof x)z then z = (unbox typeof x)((typeof x)z op y) |
3024 // or if x == (typeof x)z then z = (unbox typeof x)((typeof x)z op y) |
2988 // (but without recomputing x) |
3025 // (but without recomputing x) |
2989 JCTree newTree = abstractLval(tree.lhs, new TreeBuilder() { |
3026 JCTree newTree = abstractLval(tree.lhs, new TreeBuilder() { |
2990 public JCTree build(final JCTree lhs) { |
3027 public JCTree build(final JCTree lhs) { |
2991 int newTag = tree.getTag() - JCTree.ASGOffset; |
3028 JCTree.Tag newTag = tree.getTag().noAssignOp(); |
2992 // Erasure (TransTypes) can change the type of |
3029 // Erasure (TransTypes) can change the type of |
2993 // tree.lhs. However, we can still get the |
3030 // tree.lhs. However, we can still get the |
2994 // unerased type of tree.lhs as it is stored |
3031 // unerased type of tree.lhs as it is stored |
2995 // in tree.type in Attr. |
3032 // in tree.type in Attr. |
2996 Symbol newOperator = rs.resolveBinaryOperator(tree.pos(), |
3033 Symbol newOperator = rs.resolveBinaryOperator(tree.pos(), |
3016 tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head); |
3053 tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head); |
3017 |
3054 |
3018 // If translated left hand side is an Apply, we are |
3055 // If translated left hand side is an Apply, we are |
3019 // seeing an access method invocation. In this case, append |
3056 // seeing an access method invocation. In this case, append |
3020 // right hand side as last argument of the access method. |
3057 // right hand side as last argument of the access method. |
3021 if (tree.lhs.getTag() == JCTree.APPLY) { |
3058 if (tree.lhs.hasTag(APPLY)) { |
3022 JCMethodInvocation app = (JCMethodInvocation)tree.lhs; |
3059 JCMethodInvocation app = (JCMethodInvocation)tree.lhs; |
3023 // if operation is a += on strings, |
3060 // if operation is a += on strings, |
3024 // make sure to convert argument to string |
3061 // make sure to convert argument to string |
3025 JCExpression rhs = (((OperatorSymbol)tree.operator).opcode == string_add) |
3062 JCExpression rhs = (((OperatorSymbol)tree.operator).opcode == string_add) |
3026 ? makeString(tree.rhs) |
3063 ? makeString(tree.rhs) |
3036 JCTree lowerBoxedPostop(final JCUnary tree) { |
3073 JCTree lowerBoxedPostop(final JCUnary tree) { |
3037 // translate to tmp1=lval(e); tmp2=tmp1; tmp1 OP 1; tmp2 |
3074 // translate to tmp1=lval(e); tmp2=tmp1; tmp1 OP 1; tmp2 |
3038 // or |
3075 // or |
3039 // translate to tmp1=lval(e); tmp2=tmp1; (typeof tree)tmp1 OP 1; tmp2 |
3076 // translate to tmp1=lval(e); tmp2=tmp1; (typeof tree)tmp1 OP 1; tmp2 |
3040 // where OP is += or -= |
3077 // where OP is += or -= |
3041 final boolean cast = TreeInfo.skipParens(tree.arg).getTag() == JCTree.TYPECAST; |
3078 final boolean cast = TreeInfo.skipParens(tree.arg).hasTag(TYPECAST); |
3042 return abstractLval(tree.arg, new TreeBuilder() { |
3079 return abstractLval(tree.arg, new TreeBuilder() { |
3043 public JCTree build(final JCTree tmp1) { |
3080 public JCTree build(final JCTree tmp1) { |
3044 return abstractRval(tmp1, tree.arg.type, new TreeBuilder() { |
3081 return abstractRval(tmp1, tree.arg.type, new TreeBuilder() { |
3045 public JCTree build(final JCTree tmp2) { |
3082 public JCTree build(final JCTree tmp2) { |
3046 int opcode = (tree.getTag() == JCTree.POSTINC) |
3083 JCTree.Tag opcode = (tree.hasTag(POSTINC)) |
3047 ? JCTree.PLUS_ASG : JCTree.MINUS_ASG; |
3084 ? PLUS_ASG : MINUS_ASG; |
3048 JCTree lhs = cast |
3085 JCTree lhs = cast |
3049 ? make.TypeCast(tree.arg.type, (JCExpression)tmp1) |
3086 ? make.TypeCast(tree.arg.type, (JCExpression)tmp1) |
3050 : tmp1; |
3087 : tmp1; |
3051 JCTree update = makeAssignop(opcode, |
3088 JCTree update = makeAssignop(opcode, |
3052 lhs, |
3089 lhs, |
3057 } |
3094 } |
3058 }); |
3095 }); |
3059 } |
3096 } |
3060 |
3097 |
3061 public void visitUnary(JCUnary tree) { |
3098 public void visitUnary(JCUnary tree) { |
3062 boolean isUpdateOperator = |
3099 boolean isUpdateOperator = tree.getTag().isIncOrDecUnaryOp(); |
3063 JCTree.PREINC <= tree.getTag() && tree.getTag() <= JCTree.POSTDEC; |
|
3064 if (isUpdateOperator && !tree.arg.type.isPrimitive()) { |
3100 if (isUpdateOperator && !tree.arg.type.isPrimitive()) { |
3065 switch(tree.getTag()) { |
3101 switch(tree.getTag()) { |
3066 case JCTree.PREINC: // ++ e |
3102 case PREINC: // ++ e |
3067 // translate to e += 1 |
3103 // translate to e += 1 |
3068 case JCTree.PREDEC: // -- e |
3104 case PREDEC: // -- e |
3069 // translate to e -= 1 |
3105 // translate to e -= 1 |
3070 { |
3106 { |
3071 int opcode = (tree.getTag() == JCTree.PREINC) |
3107 JCTree.Tag opcode = (tree.hasTag(PREINC)) |
3072 ? JCTree.PLUS_ASG : JCTree.MINUS_ASG; |
3108 ? PLUS_ASG : MINUS_ASG; |
3073 JCAssignOp newTree = makeAssignop(opcode, |
3109 JCAssignOp newTree = makeAssignop(opcode, |
3074 tree.arg, |
3110 tree.arg, |
3075 make.Literal(1)); |
3111 make.Literal(1)); |
3076 result = translate(newTree, tree.type); |
3112 result = translate(newTree, tree.type); |
3077 return; |
3113 return; |
3078 } |
3114 } |
3079 case JCTree.POSTINC: // e ++ |
3115 case POSTINC: // e ++ |
3080 case JCTree.POSTDEC: // e -- |
3116 case POSTDEC: // e -- |
3081 { |
3117 { |
3082 result = translate(lowerBoxedPostop(tree), tree.type); |
3118 result = translate(lowerBoxedPostop(tree), tree.type); |
3083 return; |
3119 return; |
3084 } |
3120 } |
3085 } |
3121 } |
3086 throw new AssertionError(tree); |
3122 throw new AssertionError(tree); |
3087 } |
3123 } |
3088 |
3124 |
3089 tree.arg = boxIfNeeded(translate(tree.arg, tree), tree.type); |
3125 tree.arg = boxIfNeeded(translate(tree.arg, tree), tree.type); |
3090 |
3126 |
3091 if (tree.getTag() == JCTree.NOT && tree.arg.type.constValue() != null) { |
3127 if (tree.hasTag(NOT) && tree.arg.type.constValue() != null) { |
3092 tree.type = cfolder.fold1(bool_not, tree.arg.type); |
3128 tree.type = cfolder.fold1(bool_not, tree.arg.type); |
3093 } |
3129 } |
3094 |
3130 |
3095 // If translated left hand side is an Apply, we are |
3131 // If translated left hand side is an Apply, we are |
3096 // seeing an access method invocation. In this case, return |
3132 // seeing an access method invocation. In this case, return |
3097 // that access method invocation as result. |
3133 // that access method invocation as result. |
3098 if (isUpdateOperator && tree.arg.getTag() == JCTree.APPLY) { |
3134 if (isUpdateOperator && tree.arg.hasTag(APPLY)) { |
3099 result = tree.arg; |
3135 result = tree.arg; |
3100 } else { |
3136 } else { |
3101 result = tree; |
3137 result = tree; |
3102 } |
3138 } |
3103 } |
3139 } |
3104 |
3140 |
3105 public void visitBinary(JCBinary tree) { |
3141 public void visitBinary(JCBinary tree) { |
3106 List<Type> formals = tree.operator.type.getParameterTypes(); |
3142 List<Type> formals = tree.operator.type.getParameterTypes(); |
3107 JCTree lhs = tree.lhs = translate(tree.lhs, formals.head); |
3143 JCTree lhs = tree.lhs = translate(tree.lhs, formals.head); |
3108 switch (tree.getTag()) { |
3144 switch (tree.getTag()) { |
3109 case JCTree.OR: |
3145 case OR: |
3110 if (lhs.type.isTrue()) { |
3146 if (lhs.type.isTrue()) { |
3111 result = lhs; |
3147 result = lhs; |
3112 return; |
3148 return; |
3113 } |
3149 } |
3114 if (lhs.type.isFalse()) { |
3150 if (lhs.type.isFalse()) { |
3115 result = translate(tree.rhs, formals.tail.head); |
3151 result = translate(tree.rhs, formals.tail.head); |
3116 return; |
3152 return; |
3117 } |
3153 } |
3118 break; |
3154 break; |
3119 case JCTree.AND: |
3155 case AND: |
3120 if (lhs.type.isFalse()) { |
3156 if (lhs.type.isFalse()) { |
3121 result = lhs; |
3157 result = lhs; |
3122 return; |
3158 return; |
3123 } |
3159 } |
3124 if (lhs.type.isTrue()) { |
3160 if (lhs.type.isTrue()) { |
3184 |
3220 |
3185 JCVariableDecl indexdef = make.VarDef(index, make.Literal(INT, 0)); |
3221 JCVariableDecl indexdef = make.VarDef(index, make.Literal(INT, 0)); |
3186 indexdef.init.type = indexdef.type = syms.intType.constType(0); |
3222 indexdef.init.type = indexdef.type = syms.intType.constType(0); |
3187 |
3223 |
3188 List<JCStatement> loopinit = List.of(arraycachedef, lencachedef, indexdef); |
3224 List<JCStatement> loopinit = List.of(arraycachedef, lencachedef, indexdef); |
3189 JCBinary cond = makeBinary(JCTree.LT, make.Ident(index), make.Ident(lencache)); |
3225 JCBinary cond = makeBinary(LT, make.Ident(index), make.Ident(lencache)); |
3190 |
3226 |
3191 JCExpressionStatement step = make.Exec(makeUnary(JCTree.PREINC, make.Ident(index))); |
3227 JCExpressionStatement step = make.Exec(makeUnary(PREINC, make.Ident(index))); |
3192 |
3228 |
3193 Type elemtype = types.elemtype(tree.expr.type); |
3229 Type elemtype = types.elemtype(tree.expr.type); |
3194 JCExpression loopvarinit = make.Indexed(make.Ident(arraycache), |
3230 JCExpression loopvarinit = make.Indexed(make.Ident(arraycache), |
3195 make.Ident(index)).setType(elemtype); |
3231 make.Ident(index)).setType(elemtype); |
3196 JCVariableDecl loopvardef = (JCVariableDecl)make.VarDef(tree.var.mods, |
3232 JCVariableDecl loopvardef = (JCVariableDecl)make.VarDef(tree.var.mods, |
3590 |
3626 |
3591 public void visitSelect(JCFieldAccess tree) { |
3627 public void visitSelect(JCFieldAccess tree) { |
3592 // need to special case-access of the form C.super.x |
3628 // need to special case-access of the form C.super.x |
3593 // these will always need an access method. |
3629 // these will always need an access method. |
3594 boolean qualifiedSuperAccess = |
3630 boolean qualifiedSuperAccess = |
3595 tree.selected.getTag() == JCTree.SELECT && |
3631 tree.selected.hasTag(SELECT) && |
3596 TreeInfo.name(tree.selected) == names._super; |
3632 TreeInfo.name(tree.selected) == names._super; |
3597 tree.selected = translate(tree.selected); |
3633 tree.selected = translate(tree.selected); |
3598 if (tree.name == names._class) |
3634 if (tree.name == names._class) |
3599 result = classOf(tree.selected); |
3635 result = classOf(tree.selected); |
3600 else if (tree.name == names._this || tree.name == names._super) |
3636 else if (tree.name == names._this || tree.name == names._super) |
3640 attrEnv = env; |
3676 attrEnv = env; |
3641 this.make = make; |
3677 this.make = make; |
3642 endPositions = env.toplevel.endPositions; |
3678 endPositions = env.toplevel.endPositions; |
3643 currentClass = null; |
3679 currentClass = null; |
3644 currentMethodDef = null; |
3680 currentMethodDef = null; |
3645 outermostClassDef = (cdef.getTag() == JCTree.CLASSDEF) ? (JCClassDecl)cdef : null; |
3681 outermostClassDef = (cdef.hasTag(CLASSDEF)) ? (JCClassDecl)cdef : null; |
3646 outermostMemberDef = null; |
3682 outermostMemberDef = null; |
3647 this.translated = new ListBuffer<JCTree>(); |
3683 this.translated = new ListBuffer<JCTree>(); |
3648 classdefs = new HashMap<ClassSymbol,JCClassDecl>(); |
3684 classdefs = new HashMap<ClassSymbol,JCClassDecl>(); |
3649 actualSymbols = new HashMap<Symbol,Symbol>(); |
3685 actualSymbols = new HashMap<Symbol,Symbol>(); |
3650 freevarCache = new HashMap<ClassSymbol,List<VarSymbol>>(); |
3686 freevarCache = new HashMap<ClassSymbol,List<VarSymbol>>(); |
3836 |
3872 |
3837 JCIdent id1 = make.Ident(ordinalSymbol); |
3873 JCIdent id1 = make.Ident(ordinalSymbol); |
3838 |
3874 |
3839 JCIdent fLocUsageId = make.Ident(otherVarSym); |
3875 JCIdent fLocUsageId = make.Ident(otherVarSym); |
3840 JCExpression sel = make.Select(fLocUsageId, ordinalSymbol); |
3876 JCExpression sel = make.Select(fLocUsageId, ordinalSymbol); |
3841 JCBinary bin = makeBinary(JCTree.MINUS, id1, sel); |
3877 JCBinary bin = makeBinary(MINUS, id1, sel); |
3842 JCReturn ret = make.Return(bin); |
3878 JCReturn ret = make.Return(bin); |
3843 blockStatements.append(ret); |
3879 blockStatements.append(ret); |
3844 JCMethodDecl compareToMethod = make.MethodDef((MethodSymbol)compareToSym, |
3880 JCMethodDecl compareToMethod = make.MethodDef((MethodSymbol)compareToSym, |
3845 make.Block(0L, |
3881 make.Block(0L, |
3846 blockStatements.toList())); |
3882 blockStatements.toList())); |