2252 return builder.build(lval); |
2252 return builder.build(lval); |
2253 case SELECT: { |
2253 case SELECT: { |
2254 final JCFieldAccess s = (JCFieldAccess)lval; |
2254 final JCFieldAccess s = (JCFieldAccess)lval; |
2255 Symbol lid = TreeInfo.symbol(s.selected); |
2255 Symbol lid = TreeInfo.symbol(s.selected); |
2256 if (lid != null && lid.kind == TYP) return builder.build(lval); |
2256 if (lid != null && lid.kind == TYP) return builder.build(lval); |
2257 return abstractRval(s.selected, new TreeBuilder() { |
2257 return abstractRval(s.selected, selected -> builder.build(make.Select(selected, s.sym))); |
2258 public JCExpression build(final JCExpression selected) { |
|
2259 return builder.build(make.Select(selected, s.sym)); |
|
2260 } |
|
2261 }); |
|
2262 } |
2258 } |
2263 case INDEXED: { |
2259 case INDEXED: { |
2264 final JCArrayAccess i = (JCArrayAccess)lval; |
2260 final JCArrayAccess i = (JCArrayAccess)lval; |
2265 return abstractRval(i.indexed, new TreeBuilder() { |
2261 return abstractRval(i.indexed, indexed -> abstractRval(i.index, syms.intType, index -> { |
2266 public JCExpression build(final JCExpression indexed) { |
2262 JCExpression newLval = make.Indexed(indexed, index); |
2267 return abstractRval(i.index, syms.intType, new TreeBuilder() { |
2263 newLval.setType(i.type); |
2268 public JCExpression build(final JCExpression index) { |
2264 return builder.build(newLval); |
2269 JCExpression newLval = make.Indexed(indexed, index); |
2265 })); |
2270 newLval.setType(i.type); |
|
2271 return builder.build(newLval); |
|
2272 } |
|
2273 }); |
|
2274 } |
|
2275 }); |
|
2276 } |
2266 } |
2277 case TYPECAST: { |
2267 case TYPECAST: { |
2278 return abstractLval(((JCTypeCast)lval).expr, builder); |
2268 return abstractLval(((JCTypeCast)lval).expr, builder); |
2279 } |
2269 } |
2280 } |
2270 } |
2281 throw new AssertionError(lval); |
2271 throw new AssertionError(lval); |
2282 } |
2272 } |
2283 |
2273 |
2284 // evaluate and discard the first expression, then evaluate the second. |
2274 // evaluate and discard the first expression, then evaluate the second. |
2285 JCExpression makeComma(final JCExpression expr1, final JCExpression expr2) { |
2275 JCExpression makeComma(final JCExpression expr1, final JCExpression expr2) { |
2286 return abstractRval(expr1, new TreeBuilder() { |
2276 return abstractRval(expr1, discarded -> expr2); |
2287 public JCExpression build(final JCExpression discarded) { |
|
2288 return expr2; |
|
2289 } |
|
2290 }); |
|
2291 } |
2277 } |
2292 |
2278 |
2293 /************************************************************************** |
2279 /************************************************************************** |
2294 * Translation methods |
2280 * Translation methods |
2295 *************************************************************************/ |
2281 *************************************************************************/ |
3193 |
3179 |
3194 if (boxingReq || depScanner.dependencyFound) { |
3180 if (boxingReq || depScanner.dependencyFound) { |
3195 // boxing required; need to rewrite as x = (unbox typeof x)(x op y); |
3181 // boxing required; need to rewrite as x = (unbox typeof x)(x op y); |
3196 // or if x == (typeof x)z then z = (unbox typeof x)((typeof x)z op y) |
3182 // or if x == (typeof x)z then z = (unbox typeof x)((typeof x)z op y) |
3197 // (but without recomputing x) |
3183 // (but without recomputing x) |
3198 JCTree newTree = abstractLval(tree.lhs, new TreeBuilder() { |
3184 JCTree newTree = abstractLval(tree.lhs, lhs -> { |
3199 public JCExpression build(final JCExpression lhs) { |
3185 Tag newTag = tree.getTag().noAssignOp(); |
3200 JCTree.Tag newTag = tree.getTag().noAssignOp(); |
3186 // Erasure (TransTypes) can change the type of |
3201 // Erasure (TransTypes) can change the type of |
3187 // tree.lhs. However, we can still get the |
3202 // tree.lhs. However, we can still get the |
3188 // unerased type of tree.lhs as it is stored |
3203 // unerased type of tree.lhs as it is stored |
3189 // in tree.type in Attr. |
3204 // in tree.type in Attr. |
3190 OperatorSymbol newOperator = operators.resolveBinary(tree, |
3205 OperatorSymbol newOperator = operators.resolveBinary(tree, |
3191 newTag, |
3206 newTag, |
3192 tree.type, |
3207 tree.type, |
3193 tree.rhs.type); |
3208 tree.rhs.type); |
3194 //Need to use the "lhs" at two places, once on the future left hand side |
3209 //Need to use the "lhs" at two places, once on the future left hand side |
3195 //and once in the future binary operator. But further processing may change |
3210 //and once in the future binary operator. But further processing may change |
3196 //the components of the tree in place (see visitSelect for e.g. <Class>.super.<ident>), |
3211 //the components of the tree in place (see visitSelect for e.g. <Class>.super.<ident>), |
3197 //so cloning the tree to avoid interference between the uses: |
3212 //so cloning the tree to avoid interference between the uses: |
3198 JCExpression expr = (JCExpression) lhs.clone(); |
3213 JCExpression expr = (JCExpression) lhs.clone(); |
3199 if (expr.type != tree.type) |
3214 if (expr.type != tree.type) |
3200 expr = make.TypeCast(tree.type, expr); |
3215 expr = make.TypeCast(tree.type, expr); |
3201 JCBinary opResult = make.Binary(newTag, expr, tree.rhs); |
3216 JCBinary opResult = make.Binary(newTag, expr, tree.rhs); |
3202 opResult.operator = newOperator; |
3217 opResult.operator = newOperator; |
3203 opResult.type = newOperator.type.getReturnType(); |
3218 opResult.type = newOperator.type.getReturnType(); |
3204 JCExpression newRhs = boxingReq ? |
3219 JCExpression newRhs = boxingReq ? |
3205 make.TypeCast(types.unboxedType(tree.type), opResult) : |
3220 make.TypeCast(types.unboxedType(tree.type), opResult) : |
3206 opResult; |
3221 opResult; |
3207 return make.Assign(lhs, newRhs).setType(tree.type); |
3222 return make.Assign(lhs, newRhs).setType(tree.type); |
3208 }); |
3223 } |
|
3224 }); |
|
3225 result = translate(newTree); |
3209 result = translate(newTree); |
3226 return; |
3210 return; |
3227 } |
3211 } |
3228 tree.lhs = translate(tree.lhs, tree); |
3212 tree.lhs = translate(tree.lhs, tree); |
3229 tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head); |
3213 tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head); |
3285 // translate to tmp1=lval(e); tmp2=tmp1; tmp1 OP 1; tmp2 |
3269 // translate to tmp1=lval(e); tmp2=tmp1; tmp1 OP 1; tmp2 |
3286 // or |
3270 // or |
3287 // translate to tmp1=lval(e); tmp2=tmp1; (typeof tree)tmp1 OP 1; tmp2 |
3271 // translate to tmp1=lval(e); tmp2=tmp1; (typeof tree)tmp1 OP 1; tmp2 |
3288 // where OP is += or -= |
3272 // where OP is += or -= |
3289 final boolean cast = TreeInfo.skipParens(tree.arg).hasTag(TYPECAST); |
3273 final boolean cast = TreeInfo.skipParens(tree.arg).hasTag(TYPECAST); |
3290 return abstractLval(tree.arg, new TreeBuilder() { |
3274 return abstractLval(tree.arg, tmp1 -> abstractRval(tmp1, tree.arg.type, tmp2 -> { |
3291 public JCExpression build(final JCExpression tmp1) { |
3275 Tag opcode = (tree.hasTag(POSTINC)) |
3292 return abstractRval(tmp1, tree.arg.type, new TreeBuilder() { |
3276 ? PLUS_ASG : MINUS_ASG; |
3293 public JCExpression build(final JCExpression tmp2) { |
3277 //"tmp1" and "tmp2" may refer to the same instance |
3294 JCTree.Tag opcode = (tree.hasTag(POSTINC)) |
3278 //(for e.g. <Class>.super.<ident>). But further processing may |
3295 ? PLUS_ASG : MINUS_ASG; |
3279 //change the components of the tree in place (see visitSelect), |
3296 //"tmp1" and "tmp2" may refer to the same instance |
3280 //so cloning the tree to avoid interference between the two uses: |
3297 //(for e.g. <Class>.super.<ident>). But further processing may |
3281 JCExpression lhs = (JCExpression)tmp1.clone(); |
3298 //change the components of the tree in place (see visitSelect), |
3282 lhs = cast |
3299 //so cloning the tree to avoid interference between the two uses: |
3283 ? make.TypeCast(tree.arg.type, lhs) |
3300 JCExpression lhs = (JCExpression)tmp1.clone(); |
3284 : lhs; |
3301 lhs = cast |
3285 JCExpression update = makeAssignop(opcode, |
3302 ? make.TypeCast(tree.arg.type, lhs) |
3286 lhs, |
3303 : lhs; |
3287 make.Literal(1)); |
3304 JCExpression update = makeAssignop(opcode, |
3288 return makeComma(update, tmp2); |
3305 lhs, |
3289 })); |
3306 make.Literal(1)); |
|
3307 return makeComma(update, tmp2); |
|
3308 } |
|
3309 }); |
|
3310 } |
|
3311 }); |
|
3312 } |
3290 } |
3313 |
3291 |
3314 public void visitUnary(JCUnary tree) { |
3292 public void visitUnary(JCUnary tree) { |
3315 boolean isUpdateOperator = tree.getTag().isIncOrDecUnaryOp(); |
3293 boolean isUpdateOperator = tree.getTag().isIncOrDecUnaryOp(); |
3316 if (isUpdateOperator && !tree.arg.type.isPrimitive()) { |
3294 if (isUpdateOperator && !tree.arg.type.isPrimitive()) { |