private Expression operationWithConstantValue( BinaryExpression binExp, java.lang.Class expectedClass, Expression constantExp, boolean constantOnLeft, boolean operationWithSideEffect) { Expression exp; if (operationWithSideEffect) { MethodAccess call = new MethodAccess(); call.expression = new This(); exp = call; } else { exp = new IdExpression(); } exp.type = constantExp.type; if (constantOnLeft) { binExp.right = exp; binExp.left = constantExp; } else { binExp.left = exp; binExp.right = constantExp; } if (null == expectedClass) expectedClass = MethodAccess.class; return expressionSimplificationTester(binExp, expectedClass, constantExp.type, 0, false); }
public void positionStmtsAfterEnumInitStmts(List<Statement> staticFieldStatements) { MethodNode method = getOrAddStaticConstructorNode(); Statement statement = method.getCode(); if (statement instanceof BlockStatement) { BlockStatement block = (BlockStatement) statement; // add given statements for explicitly declared static fields just after enum-special fields // are found - the $VALUES binary expression marks the end of such fields. List<Statement> blockStatements = block.getStatements(); ListIterator<Statement> litr = blockStatements.listIterator(); while (litr.hasNext()) { Statement stmt = litr.next(); if (stmt instanceof ExpressionStatement && ((ExpressionStatement) stmt).getExpression() instanceof BinaryExpression) { BinaryExpression bExp = (BinaryExpression) ((ExpressionStatement) stmt).getExpression(); if (bExp.getLeftExpression() instanceof FieldExpression) { FieldExpression fExp = (FieldExpression) bExp.getLeftExpression(); if (fExp.getFieldName().equals("$VALUES")) { for (Statement tmpStmt : staticFieldStatements) { litr.add(tmpStmt); } } } } } } }
@Override public Void visitBinaryExpression(BinaryExpression node) { visit(node.getLeftOperand()); writer.print(' '); writer.print(node.getOperator().getLexeme()); writer.print(' '); visit(node.getRightOperand()); return null; }
public void generateOptimizedStringConcatenationCreation( BlockScope blockScope, CodeStream codeStream, int typeID) { // keep implementation in sync with BinaryExpression // #generateOptimizedStringConcatenationCreation if (this.referencesTable == null) { super.generateOptimizedStringConcatenationCreation(blockScope, codeStream, typeID); } else { if ((((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS) && ((this.bits & ASTNode.ReturnTypeIDMASK) == TypeIds.T_JavaLangString) && this.constant == Constant.NotAConstant) { int pc = codeStream.position; BinaryExpression cursor = this.referencesTable[this.arity - 1]; // silence warnings int restart = 0; for (restart = this.arity - 1; restart >= 0; restart--) { if (((((cursor = this.referencesTable[restart]).bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS) && ((cursor.bits & ASTNode.ReturnTypeIDMASK) == TypeIds.T_JavaLangString)) { if (cursor.constant != Constant.NotAConstant) { codeStream.newStringContatenation(); // new: java.lang.StringBuffer codeStream.dup(); codeStream.ldc(cursor.constant.stringValue()); codeStream.invokeStringConcatenationStringConstructor(); // invokespecial: java.lang.StringBuffer.<init>(Ljava.lang.String;)V break; } } else { cursor.generateOptimizedStringConcatenationCreation( blockScope, codeStream, cursor.implicitConversion & TypeIds.COMPILE_TYPE_MASK); break; } } restart++; if (restart == 0) { // reached the leftmost expression cursor.left.generateOptimizedStringConcatenationCreation( blockScope, codeStream, cursor.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK); } int pcAux; for (int i = restart; i < this.arity; i++) { codeStream.recordPositionsFrom(pc, (cursor = this.referencesTable[i]).left.sourceStart); pcAux = codeStream.position; cursor.right.generateOptimizedStringConcatenation( blockScope, codeStream, cursor.right.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.recordPositionsFrom(pcAux, cursor.right.sourceStart); } codeStream.recordPositionsFrom(pc, this.left.sourceStart); pc = codeStream.position; this.right.generateOptimizedStringConcatenation( blockScope, codeStream, this.right.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.recordPositionsFrom(pc, this.right.sourceStart); } else { super.generateOptimizedStringConcatenationCreation(blockScope, codeStream, typeID); } } }
public void traverse(ASTVisitor visitor, BlockScope scope) { if (this.referencesTable == null) { super.traverse(visitor, scope); } else { if (visitor.visit(this, scope)) { int restart; for (restart = this.arity - 1; restart >= 0; restart--) { if (!visitor.visit(this.referencesTable[restart], scope)) { visitor.endVisit(this.referencesTable[restart], scope); break; } } restart++; // restart now points to the deepest BE for which // visit returned true, if any if (restart == 0) { this.referencesTable[0].left.traverse(visitor, scope); } for (int i = restart, end = this.arity; i < end; i++) { this.referencesTable[i].right.traverse(visitor, scope); visitor.endVisit(this.referencesTable[i], scope); } this.right.traverse(visitor, scope); } visitor.endVisit(this, scope); } }
/** Boolean operator code generation Optimized operations are: == and != */ public void generateOptimizedBoolean( BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { if (this.constant != Constant.NotAConstant) { super.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, valueRequired); return; } if (((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) { if ((this.left.implicitConversion & COMPILE_TYPE_MASK) /*compile-time*/ == T_boolean) { generateOptimizedBooleanEqual( currentScope, codeStream, trueLabel, falseLabel, valueRequired); } else { generateOptimizedNonBooleanEqual( currentScope, codeStream, trueLabel, falseLabel, valueRequired); } } else { if ((this.left.implicitConversion & COMPILE_TYPE_MASK) /*compile-time*/ == T_boolean) { generateOptimizedBooleanEqual( currentScope, codeStream, falseLabel, trueLabel, valueRequired); } else { generateOptimizedNonBooleanEqual( currentScope, codeStream, falseLabel, trueLabel, valueRequired); } } }
/** Log mutated line */ public void visit(BinaryExpression p) throws ParseTreeException { if (isSameObject(p, original)) { BinaryExpression mutant_exp; mutant_exp = (BinaryExpression) original.makeRecursiveCopy(); mutant_exp.setOperator(mutant_op); super.visit(mutant_exp); String operator = mutant_exp.operatorString(); out.print(" " + operator + " "); // ----------------------------------------------------------- mutated_line = line_num; String log_str = p.operatorString() + " => " + operator; writeLog(removeNewline(log_str)); // ------------------------------------------------------------- mutant_exp = null; } else { super.visit(p); } }
private Runnable replaceWith(final BinaryExpression newExpr) { final Mapper<?, ?> root = Mappers.getRoot(myMapper); BinaryExpression oldExpr = myMapper.getSource(); oldExpr.replaceWith(newExpr); Expression left = oldExpr.left.get(); if (left != null) { left.removeFromParent(); } Expression right = oldExpr.right.get(); if (right != null) { right.removeFromParent(); } newExpr.left.set(left); newExpr.right.set(right); new ExprBinOpTransformer().balanceOnOperationChange(newExpr).parent().get(); return CellActions.toEnd( ((BinaryExpressionMapper) root.getDescendantMapper(newExpr)).getTarget().sign); }
// Parses a binary expression private void parse(BinaryExpression be) { BinaryOperator bop = be.getOperator(); SimpleExpression lhs = new SimpleExpression(be.getLHS()); SimpleExpression rhs = new SimpleExpression(be.getRHS()); contains_side_effect |= (lhs.contains_side_effect || rhs.contains_side_effect); if (bop == BinaryOperator.SUBTRACT) { sop = ADD; SimpleExpression new_rhs = new SimpleExpression(MUL); new_rhs.add(getInt(-1)); new_rhs.add(rhs); add(lhs); add(new_rhs); } else { sop = cop.indexOf(bop); if (sop == -1) { sop = TREE; expr = be; } add(lhs); add(rhs); } }
@Override public void visitBinaryExpression(BinaryExpression be) { super.visitBinaryExpression(be); switch (be.getOperation().getType()) { case Types.EQUAL: // = assignment case Types.BITWISE_AND_EQUAL: case Types.BITWISE_OR_EQUAL: case Types.BITWISE_XOR_EQUAL: case Types.PLUS_EQUAL: case Types.MINUS_EQUAL: case Types.MULTIPLY_EQUAL: case Types.DIVIDE_EQUAL: case Types.INTDIV_EQUAL: case Types.MOD_EQUAL: case Types.POWER_EQUAL: case Types.LEFT_SHIFT_EQUAL: case Types.RIGHT_SHIFT_EQUAL: case Types.RIGHT_SHIFT_UNSIGNED_EQUAL: checkFinalFieldAccess(be.getLeftExpression()); break; default: break; } }
/** * Attempts to parse a syntactic assignment expression from token stream. If parsing fails the * stream is reset to its initial position. * * @param tokens source token stream * @return Expression object or null if tokens don't form a valid expression */ public static Expression parse(TokenStream tokens) { Position pos = tokens.getPosition(); tokens.pushMark(); Expression expr = BinaryExpression.parse(tokens); if (expr != null) { tokens.pushMark(); Expression right = null; String op = tokens.read().toString(); if (assignmentOperators.containsKey(op)) right = AssignmentExpression.parse(tokens); tokens.popMark(right == null); if (right != null) expr = new AssignmentExpression(op, expr, right, pos); } tokens.popMark(expr == null); return expr; }
protected Expression transformBinaryExpression(BinaryExpression be) { int type = be.getOperation().getType(); boolean oldInLeftExpression; Expression right = transform(be.getRightExpression()); be.setRightExpression(right); Expression left; if (type == Types.EQUAL && be.getLeftExpression() instanceof VariableExpression) { oldInLeftExpression = inLeftExpression; inLeftExpression = true; left = transform(be.getLeftExpression()); inLeftExpression = oldInLeftExpression; if (left instanceof StaticMethodCallExpression) { StaticMethodCallExpression smce = (StaticMethodCallExpression) left; StaticMethodCallExpression result = new StaticMethodCallExpression(smce.getOwnerType(), smce.getMethod(), right); setSourcePosition(result, be); return result; } } else { left = transform(be.getLeftExpression()); } be.setLeftExpression(left); return be; }
public void visit(BinaryExpression entity) { wGetVisitor1().visit(entity.getLeftExpr()); wGetVisitor1().visit(entity.getOperator()); wGetVisitor1().visit(entity.getRightExpr()); }
Expression transformMethodCallExpression(final MethodCallExpression expr) { Expression objectExpression = expr.getObjectExpression(); if (expr.isSafe()) { MethodCallExpression notSafe = new MethodCallExpression(objectExpression, expr.getMethod(), expr.getArguments()); notSafe.copyNodeMetaData(expr); notSafe.setSpreadSafe(expr.isSpreadSafe()); notSafe.setSourcePosition(expr); notSafe.setMethodTarget(expr.getMethodTarget()); TernaryExpression texpr = new TernaryExpression( new BooleanExpression( new BinaryExpression( objectExpression, Token.newSymbol( "!=", objectExpression.getLineNumber(), objectExpression.getColumnNumber()), ConstantExpression.NULL)), notSafe, ConstantExpression.NULL); return staticCompilationTransformer.transform(texpr); } ClassNode type = staticCompilationTransformer .getTypeChooser() .resolveType(objectExpression, staticCompilationTransformer.getClassNode()); if (type != null && type.isArray()) { String method = expr.getMethodAsString(); ClassNode componentType = type.getComponentType(); if ("getAt".equals(method)) { Expression arguments = expr.getArguments(); if (arguments instanceof TupleExpression) { List<Expression> argList = ((TupleExpression) arguments).getExpressions(); if (argList.size() == 1) { Expression indexExpr = argList.get(0); ClassNode argType = staticCompilationTransformer .getTypeChooser() .resolveType(indexExpr, staticCompilationTransformer.getClassNode()); ClassNode indexType = ClassHelper.getWrapper(argType); if (componentType.isEnum() && ClassHelper.Number_TYPE == indexType) { // workaround for generated code in enums which use .next() returning a Number indexType = ClassHelper.Integer_TYPE; } if (argType != null && ClassHelper.Integer_TYPE == indexType) { BinaryExpression binaryExpression = new BinaryExpression( objectExpression, Token.newSymbol("[", indexExpr.getLineNumber(), indexExpr.getColumnNumber()), indexExpr); binaryExpression.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, componentType); return staticCompilationTransformer.transform(binaryExpression); } } } } if ("putAt".equals(method)) { Expression arguments = expr.getArguments(); if (arguments instanceof TupleExpression) { List<Expression> argList = ((TupleExpression) arguments).getExpressions(); if (argList.size() == 2) { Expression indexExpr = argList.get(0); Expression objExpr = argList.get(1); ClassNode argType = staticCompilationTransformer .getTypeChooser() .resolveType(indexExpr, staticCompilationTransformer.getClassNode()); if (argType != null && ClassHelper.Integer_TYPE == ClassHelper.getWrapper(argType)) { BinaryExpression arrayGet = new BinaryExpression( objectExpression, Token.newSymbol("[", indexExpr.getLineNumber(), indexExpr.getColumnNumber()), indexExpr); arrayGet.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, componentType); BinaryExpression assignment = new BinaryExpression( arrayGet, Token.newSymbol("=", objExpr.getLineNumber(), objExpr.getColumnNumber()), objExpr); return staticCompilationTransformer.transform(assignment); } } } } } return staticCompilationTransformer.superTransform(expr); }
/** Boolean operator code generation Optimized operations are: || */ public void generateOptimizedBoolean( BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) { if (this.constant != Constant.NotAConstant) { super.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, valueRequired); return; } // <expr> || false --> <expr> Constant cst = this.right.constant; if (cst != Constant.NotAConstant && cst.booleanValue() == false) { int pc = codeStream.position; this.left.generateOptimizedBoolean( currentScope, codeStream, trueLabel, falseLabel, valueRequired); if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } codeStream.recordPositionsFrom(pc, this.sourceStart); return; } cst = this.left.optimizedBooleanConstant(); boolean leftIsConst = cst != Constant.NotAConstant; boolean leftIsTrue = leftIsConst && cst.booleanValue() == true; cst = this.right.optimizedBooleanConstant(); boolean rightIsConst = cst != Constant.NotAConstant; boolean rightIsTrue = rightIsConst && cst.booleanValue() == true; // default case generateOperands: { if (falseLabel == null) { if (trueLabel != null) { // implicit falling through the FALSE case this.left.generateOptimizedBoolean( currentScope, codeStream, trueLabel, null, !leftIsConst); // need value, e.g. if (a == 1 || ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a==1 if (leftIsTrue) { if (valueRequired) codeStream.goto_(trueLabel); codeStream.recordPositionsFrom(codeStream.position, this.left.sourceEnd); break generateOperands; // no need to generate right operand } if (this.rightInitStateIndex != -1) { codeStream.addDefinitelyAssignedVariables(currentScope, this.rightInitStateIndex); } this.right.generateOptimizedBoolean( currentScope, codeStream, trueLabel, null, valueRequired && !rightIsConst); if (valueRequired && rightIsTrue) { codeStream.goto_(trueLabel); codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd); } } } else { // implicit falling through the TRUE case if (trueLabel == null) { BranchLabel internalTrueLabel = new BranchLabel(codeStream); this.left.generateOptimizedBoolean( currentScope, codeStream, internalTrueLabel, null, !leftIsConst); // need value, e.g. if (a == 1 || ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a==1 if (leftIsTrue) { internalTrueLabel.place(); break generateOperands; // no need to generate right operand } if (this.rightInitStateIndex != -1) { codeStream.addDefinitelyAssignedVariables(currentScope, this.rightInitStateIndex); } this.right.generateOptimizedBoolean( currentScope, codeStream, null, falseLabel, valueRequired && !rightIsConst); int pc = codeStream.position; if (valueRequired && rightIsConst && !rightIsTrue) { codeStream.goto_(falseLabel); codeStream.recordPositionsFrom(pc, this.sourceEnd); } internalTrueLabel.place(); } else { // no implicit fall through TRUE/FALSE --> should never occur } } } if (this.mergedInitStateIndex != -1) { codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex); } }
public void visitBinaryExpression(BinaryExpression binaryExpression) throws Exception { binaryExpression.getLeftExpression().accept(this); binaryExpression.getRightExpression().accept(this); }
@SuppressWarnings("unchecked") @Override public Function<Object[], ?> visit(BinaryExpression e) { final Function<Object[], ?> first = e.getFirst().accept(this); final Function<Object[], ?> second = e.getSecond().accept(this); switch (e.getExpressionType()) { case ExpressionType.Add: return normalize( add((Function<Object[], Number>) first, (Function<Object[], Number>) second)); case ExpressionType.BitwiseAnd: return normalize( bitwiseAnd((Function<Object[], Number>) first, (Function<Object[], Number>) second)); case ExpressionType.LogicalAnd: return normalize( and((Function<Object[], Boolean>) first, (Function<Object[], Boolean>) second)); case ExpressionType.ArrayIndex: return t -> Array.get(first.apply(t), (Integer) second.apply(t)); // return new Function<Object, Object[]>() { // // @Override // public Object invoke(Object[] t) throws Throwable { // return Array.get(first.invoke(t), (Integer) second // .invoke(t)); // } // }; // case ExpressionType.Coalesce: // return coalesce((Function<?, Object[]>) first, // (Function<?, Object[]>) second); case ExpressionType.Conditional: return iif((Function<Object[], Boolean>) e.getOperator().accept(this), first, second); case ExpressionType.Divide: return normalize( divide((Function<Object[], Number>) first, (Function<Object[], Number>) second)); case ExpressionType.Equal: return normalize(equal(first, second)); case ExpressionType.ExclusiveOr: return normalize( xor((Function<Object[], Number>) first, (Function<Object[], Number>) second)); case ExpressionType.GreaterThan: return normalize( greaterThan((Function<Object[], Number>) first, (Function<Object[], Number>) second)); case ExpressionType.GreaterThanOrEqual: return normalize( greaterThanOrEqual( (Function<Object[], Number>) first, (Function<Object[], Number>) second)); case ExpressionType.LeftShift: return normalize( shiftLeft((Function<Object[], Number>) first, (Function<Object[], Number>) second)); case ExpressionType.LessThan: return normalize( lessThan((Function<Object[], Number>) first, (Function<Object[], Number>) second)); case ExpressionType.LessThanOrEqual: return normalize( lessThanOrEqual( (Function<Object[], Number>) first, (Function<Object[], Number>) second)); case ExpressionType.Modulo: return normalize( modulo((Function<Object[], Number>) first, (Function<Object[], Number>) second)); case ExpressionType.Multiply: return normalize( multiply((Function<Object[], Number>) first, (Function<Object[], Number>) second)); case ExpressionType.NotEqual: return normalize(equal(first, second).negate()); case ExpressionType.BitwiseOr: return normalize( bitwiseOr((Function<Object[], Number>) first, (Function<Object[], Number>) second)); case ExpressionType.LogicalOr: return normalize( or((Function<Object[], Boolean>) first, (Function<Object[], Boolean>) second)); // case ExpressionType.Power: // return power((Function<Number, Object[]>) first, // (Function<Number, Object[]>) second); case ExpressionType.RightShift: return normalize( shiftRight((Function<Object[], Number>) first, (Function<Object[], Number>) second)); case ExpressionType.Subtract: return normalize( subtract((Function<Object[], Number>) first, (Function<Object[], Number>) second)); case ExpressionType.InstanceOf: return normalize(instanceOf(first, (Class<?>) second.apply(null))); default: throw new IllegalArgumentException(ExpressionType.toString(e.getExpressionType())); } }
@Override public Object visitBinaryExpression(BinaryExpression binaryExpression, Object arg) throws Exception { MethodVisitor mv = ((InheritedAttributes) arg).mv; Kind op = binaryExpression.op.kind; binaryExpression.setType(binaryExpression.expression0.getType()); switch (op) { case PLUS: if (binaryExpression.expression0.getType().equalsIgnoreCase(intType) || binaryExpression.expression0.getType().equalsIgnoreCase(booleanType)) { binaryExpression.expression0.visit(this, arg); binaryExpression.expression1.visit(this, arg); mv.visitInsn(IADD); } else if (binaryExpression.expression0.getType().equalsIgnoreCase(stringType)) { mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); mv.visitInsn(DUP); binaryExpression.expression0.visit(this, arg); mv.visitMethodInsn( INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false); binaryExpression.expression1.visit(this, arg); mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); } break; case MINUS: binaryExpression.expression0.visit(this, arg); binaryExpression.expression1.visit(this, arg); mv.visitInsn(ISUB); break; case TIMES: binaryExpression.expression0.visit(this, arg); binaryExpression.expression1.visit(this, arg); mv.visitInsn(IMUL); break; case DIV: binaryExpression.expression0.visit(this, arg); binaryExpression.expression1.visit(this, arg); mv.visitInsn(IDIV); break; case LSHIFT: binaryExpression.expression0.visit(this, arg); binaryExpression.expression1.visit(this, arg); mv.visitInsn(ISHL); break; case RSHIFT: binaryExpression.expression0.visit(this, arg); binaryExpression.expression1.visit(this, arg); mv.visitInsn(ISHR); break; case BAR: binaryExpression.expression0.visit(this, arg); binaryExpression.expression1.visit(this, arg); mv.visitInsn(IOR); break; case AND: binaryExpression.expression0.visit(this, arg); Label l1 = new Label(); mv.visitJumpInsn(IFEQ, l1); binaryExpression.expression1.visit(this, arg); mv.visitJumpInsn(IFEQ, l1); mv.visitInsn(ICONST_1); Label l2 = new Label(); mv.visitJumpInsn(GOTO, l2); mv.visitLabel(l1); mv.visitInsn(ICONST_0); mv.visitLabel(l2); break; case EQUAL: Label falseLabel = new Label(); Label end = new Label(); if (binaryExpression.expression0.getType().equalsIgnoreCase(intType) || binaryExpression.expression0.getType().equalsIgnoreCase(booleanType)) { binaryExpression.expression0.visit(this, arg); binaryExpression.expression1.visit(this, arg); mv.visitJumpInsn(IF_ICMPNE, falseLabel); mv.visitInsn(ICONST_1); mv.visitJumpInsn(GOTO, end); mv.visitLabel(falseLabel); mv.visitInsn(ICONST_0); mv.visitLabel(end); } else { binaryExpression.expression0.visit(this, arg); binaryExpression.expression1.visit(this, arg); mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/String", "compareTo", "(Ljava/lang/String;)I", false); mv.visitJumpInsn(IFNE, falseLabel); mv.visitInsn(ICONST_1); mv.visitJumpInsn(GOTO, end); mv.visitLabel(falseLabel); mv.visitInsn(ICONST_0); mv.visitLabel(end); } binaryExpression.setType(booleanType); break; case NOTEQUAL: falseLabel = new Label(); end = new Label(); if (binaryExpression.expression0.getType().equalsIgnoreCase(intType) || binaryExpression.expression0.getType().equalsIgnoreCase(booleanType)) { binaryExpression.expression0.visit(this, arg); binaryExpression.expression1.visit(this, arg); mv.visitJumpInsn(IF_ICMPEQ, falseLabel); mv.visitInsn(ICONST_1); mv.visitJumpInsn(GOTO, end); mv.visitLabel(falseLabel); mv.visitInsn(ICONST_0); mv.visitLabel(end); } else { binaryExpression.expression0.visit(this, arg); binaryExpression.expression1.visit(this, arg); mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/String", "compareTo", "(Ljava/lang/String;)I", false); mv.visitJumpInsn(IFEQ, falseLabel); mv.visitInsn(ICONST_1); mv.visitJumpInsn(GOTO, end); mv.visitLabel(falseLabel); mv.visitInsn(ICONST_0); mv.visitLabel(end); } binaryExpression.setType(booleanType); break; case LT: falseLabel = new Label(); binaryExpression.expression0.visit(this, arg); binaryExpression.expression1.visit(this, arg); mv.visitJumpInsn(IF_ICMPGE, falseLabel); mv.visitInsn(ICONST_1); end = new Label(); mv.visitJumpInsn(GOTO, end); mv.visitLabel(falseLabel); mv.visitInsn(ICONST_0); mv.visitLabel(end); binaryExpression.setType(booleanType); break; case GT: falseLabel = new Label(); binaryExpression.expression0.visit(this, arg); binaryExpression.expression1.visit(this, arg); mv.visitJumpInsn(IF_ICMPLE, falseLabel); mv.visitInsn(ICONST_1); end = new Label(); mv.visitJumpInsn(GOTO, end); mv.visitLabel(falseLabel); mv.visitInsn(ICONST_0); mv.visitLabel(end); binaryExpression.setType(booleanType); break; case LE: falseLabel = new Label(); binaryExpression.expression0.visit(this, arg); binaryExpression.expression1.visit(this, arg); mv.visitJumpInsn(IF_ICMPGT, falseLabel); mv.visitInsn(ICONST_1); end = new Label(); mv.visitJumpInsn(GOTO, end); mv.visitLabel(falseLabel); mv.visitInsn(ICONST_0); mv.visitLabel(end); binaryExpression.setType(booleanType); break; case GE: falseLabel = new Label(); binaryExpression.expression0.visit(this, arg); binaryExpression.expression1.visit(this, arg); mv.visitJumpInsn(IF_ICMPLT, falseLabel); mv.visitInsn(ICONST_1); end = new Label(); mv.visitJumpInsn(GOTO, end); mv.visitLabel(falseLabel); mv.visitInsn(ICONST_0); mv.visitLabel(end); binaryExpression.setType(booleanType); break; } return binaryExpression.getType(); // throw new UnsupportedOperationException("code generation not yet implemented"); }
public void visitBinaryExpression(BinaryExpression expression) { expression.getLeftExpression().visit(this); expression.getRightExpression().visit(this); }
/** Normalization for points-to analysis. */ private static Expression normalize(Expression arg, Symbol param) { Expression ret = arg.clone(); // default behavior. // Converts array accesses to address-of expressions. if (ret instanceof ArrayAccess) { ArrayAccess array = (ArrayAccess) ret; // Normalize the array name. Expression name = normalize(array.getArrayName(), null); Symbol base = SymbolTools.getSymbolOf(name); if (base != null && param != null && SymbolTools.isPointerParameter(param)) { // case 1: the base symbol has an array specifier. // --> - keeps the array indices while adding trailing [0]. // - converts to address-of expression. // - adds dereference operator if base is a formal parameter if (SymbolTools.isArray(base)) { // Adds a trailing subscript "[0]" intentionally. array.addIndex(new IntegerLiteral(0)); ret = new UnaryExpression(UnaryOperator.ADDRESS_OF, ret); // Formal parameter is normalized: a[10] to (*a)[10]. // This conversion is used only internally (not legal in C). if (SymbolTools.isPointerParameter(base)) { array .getArrayName() .swapWith(new UnaryExpression(UnaryOperator.DEREFERENCE, name.clone())); } // case 2: the base symbol does not have an array specifier. // --> just take the base object while converting a subscript // to a dereference. } else { ret = name; for (int i = 0; i < array.getNumIndices(); i++) { ret = new UnaryExpression(UnaryOperator.DEREFERENCE, ret.clone()); } } } else { // just normalizes the array name. array.getArrayName().swapWith(name); } // Removes pointer access and adds trailing dummy index for pointer // type. } else if (ret instanceof AccessExpression) { AccessExpression access = (AccessExpression) ret; // POINTER_ACCESS to MEMBER_ACCESS if (access.getOperator() == AccessOperator.POINTER_ACCESS) { // Normalize the LHS. Expression lhs = normalize(access.getLHS(), null); ret = new AccessExpression( new UnaryExpression(UnaryOperator.DEREFERENCE, lhs.clone()), AccessOperator.MEMBER_ACCESS, access.getRHS().clone()); } // Pointer type to address-of expression. if (param != null && SymbolTools.isPointerParameter(param)) { ret = new UnaryExpression( UnaryOperator.ADDRESS_OF, new ArrayAccess(ret.clone(), new IntegerLiteral(0))); } // Just normalize the expression child. } else if (ret instanceof UnaryExpression) { UnaryExpression ue = (UnaryExpression) ret; ue.setExpression(normalize(ue.getExpression(), null)); // Tries to convert simple pointer arithmetic to array access. } else if (ret instanceof BinaryExpression) { BinaryExpression be = (BinaryExpression) ret; Expression lhs = normalize(be.getLHS(), null); Expression rhs = normalize(be.getRHS(), null); if (param != null && SymbolTools.isPointerParameter(param) && be.getOperator() == BinaryOperator.ADD) { if (isPointerArithmeticOperand(lhs, rhs)) { ret = new UnaryExpression( UnaryOperator.ADDRESS_OF, new ArrayAccess(rhs.clone(), lhs.clone())); } else if (isPointerArithmeticOperand(rhs, lhs)) { ret = new UnaryExpression( UnaryOperator.ADDRESS_OF, new ArrayAccess(lhs.clone(), rhs.clone())); } } else { ret = new BinaryExpression(lhs.clone(), be.getOperator(), rhs.clone()); } // Type cast is discarded. } else if (ret instanceof Typecast) { ret = (Expression) ret.getChildren().get(0); } return ret; }
public void generateOptimizedStringConcatenation( BlockScope blockScope, CodeStream codeStream, int typeID) { // keep implementation in sync with BinaryExpression and Expression // #generateOptimizedStringConcatenation if (this.referencesTable == null) { super.generateOptimizedStringConcatenation(blockScope, codeStream, typeID); } else { if ((((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS) && ((this.bits & ASTNode.ReturnTypeIDMASK) == TypeIds.T_JavaLangString)) { if (this.constant != Constant.NotAConstant) { codeStream.generateConstant(this.constant, this.implicitConversion); codeStream.invokeStringConcatenationAppendForType( this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); } else { BinaryExpression cursor = this.referencesTable[0]; int restart = 0; // int cursorTypeID; int pc = codeStream.position; for (restart = this.arity - 1; restart >= 0; restart--) { if ((cursor = this.referencesTable[restart]).constant != Constant.NotAConstant) { codeStream.generateConstant(cursor.constant, cursor.implicitConversion); codeStream.invokeStringConcatenationAppendForType( cursor.implicitConversion & TypeIds.COMPILE_TYPE_MASK); break; } // never happens for now - may reconsider if we decide to // cover more than string concatenation // if (!((((cursor = this.referencesTable[restart]).bits & // ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == // OperatorIds.PLUS) & // ((cursorTypeID = cursor.bits & ASTNode.ReturnTypeIDMASK) == // TypeIds.T_JavaLangString)) { // if (cursorTypeID == T_JavaLangString && // cursor.constant != Constant.NotAConstant && // cursor.constant.stringValue().length() == 0) { // break; // optimize str + "" // } // cursor.generateCode(blockScope, codeStream, true); // codeStream.invokeStringConcatenationAppendForType( // cursorTypeID); // break; // } } restart++; if (restart == 0) { // reached the leftmost expression cursor.left.generateOptimizedStringConcatenation( blockScope, codeStream, cursor.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK); } int pcAux; for (int i = restart; i < this.arity; i++) { codeStream.recordPositionsFrom(pc, (cursor = this.referencesTable[i]).left.sourceStart); pcAux = codeStream.position; cursor.right.generateOptimizedStringConcatenation( blockScope, codeStream, cursor.right.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.recordPositionsFrom(pcAux, cursor.right.sourceStart); } codeStream.recordPositionsFrom(pc, this.left.sourceStart); pc = codeStream.position; this.right.generateOptimizedStringConcatenation( blockScope, codeStream, this.right.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.recordPositionsFrom(pc, this.right.sourceStart); } } else { super.generateOptimizedStringConcatenation(blockScope, codeStream, typeID); } } }
private void visitBinaryOperation(BinaryExpression be) { be.getLeftExpression().accept(this); be.getRightExpression().accept(this); }
@Override void XMLAttributes(final StringBuilder sb) { sb.append(" op=\"").append(BinaryExpression.encodeXML(ops.getStr(op))).append('"'); }