Logo Search packages:      
Sourcecode: janino version File versions  Download package

IClass org::codehaus::janino::UnitCompiler::compileArithmeticOperation ( final Locatable  l,
IClass  type,
Iterator  operands,
String  operator 
) throws CompileException [inline, private]

Execute an arithmetic operation on a sequence of operands. If type is non-null, the first operand with that type is already on the stack.

The following operators are supported:   | ^ & * / % + - << >> >>>

Definition at line 4477 of file UnitCompiler.java.

References org::codehaus::janino::IClassLoader::BOOLEAN, org::codehaus::janino::IClass::BOOLEAN, org::codehaus::janino::IClass::DOUBLE, org::codehaus::janino::IClass::FLOAT, org::codehaus::janino::IClass::INT, org::codehaus::janino::IClass::isPrimitiveNumeric(), org::codehaus::janino::IClass::LONG, and org::codehaus::janino::IClassLoader::STRING.

                              {
        if (
            operator == "|" ||
            operator == "^" ||
            operator == "&"
        ) {
            final int iopcode = (
                operator == "&" ? Opcode.IAND :
                operator == "|" ? Opcode.IOR  :
                operator == "^" ? Opcode.IXOR : Integer.MAX_VALUE
            );

            do {
                Java.Rvalue operand = (Java.Rvalue) operands.next();

                if (type == null) {
                    type = this.compileGetValue(operand);
                } else {
                    CodeContext.Inserter convertLhsInserter = this.codeContext.newInserter();
                    IClass rhsType = this.compileGetValue(operand);

                    if (
                        type.isPrimitiveNumeric() &&
                        rhsType.isPrimitiveNumeric()
                    ) {
                        IClass promotedType = this.binaryNumericPromotion(l, type, convertLhsInserter, rhsType);
                        if (promotedType == IClass.INT) {
                            this.writeOpcode(l, iopcode);
                        } else
                        if (promotedType == IClass.LONG) {
                            this.writeOpcode(l, iopcode + 1);
                        } else
                        {
                            this.compileError("Operator \"" + operator + "\" not defined on types \"" + type + "\" and \"" + rhsType + "\"", l.getLocation());
                        }
                        type = promotedType;
                    } else
                    if (
                        (type == IClass.BOOLEAN && this.getUnboxedType(rhsType) == IClass.BOOLEAN) ||
                        (this.getUnboxedType(type) == IClass.BOOLEAN && rhsType == IClass.BOOLEAN)
                    ) {
                        IClassLoader icl = this.iClassLoader;
                        if (type == icl.BOOLEAN) {
                            this.codeContext.pushInserter(convertLhsInserter);
                            try {
                                this.unboxingConversion(l, icl.BOOLEAN, IClass.BOOLEAN);
                            } finally {
                                this.codeContext.popInserter();
                            }
                        }
                        if (rhsType == icl.BOOLEAN) {
                            this.unboxingConversion(l, icl.BOOLEAN, IClass.BOOLEAN);
                        }
                        this.writeOpcode(l, iopcode);
                        type = IClass.BOOLEAN;
                    } else
                    {
                        this.compileError("Operator \"" + operator + "\" not defined on types \"" + type + "\" and \"" + rhsType + "\"", l.getLocation());
                        type = IClass.INT;
                    }
                }
            } while (operands.hasNext());
            return type;
        }

        if (
            operator == "*"   ||
            operator == "/"   ||
            operator == "%"   ||
            operator == "+"   ||
            operator == "-"
        ) {
            final int iopcode = (
                operator == "*"   ? Opcode.IMUL  :
                operator == "/"   ? Opcode.IDIV  :
                operator == "%"   ? Opcode.IREM  :
                operator == "+"   ? Opcode.IADD  :
                operator == "-"   ? Opcode.ISUB  : Integer.MAX_VALUE
            );

            do {
                Java.Rvalue operand = (Java.Rvalue) operands.next();

                IClass operandType = this.getType(operand);
                IClassLoader icl = this.iClassLoader;

                // String concatenation?
                if (operator == "+" && (type == icl.STRING || operandType == icl.STRING)) {
                    return this.compileStringConcatenation(l, type, operand, operands);
                }

                if (type == null) {
                    type = this.compileGetValue(operand);
                } else {
                    CodeContext.Inserter convertLhsInserter = this.codeContext.newInserter();
                    IClass rhsType = this.compileGetValue(operand);

                    type = this.binaryNumericPromotion(l, type, convertLhsInserter, rhsType);

                    int opcode;
                    if (type == IClass.INT) {
                        opcode = iopcode;
                    } else
                    if (type == IClass.LONG) {
                        opcode = iopcode + 1;
                    } else
                    if (type == IClass.FLOAT) {
                        opcode = iopcode + 2;
                    } else
                    if (type == IClass.DOUBLE) {
                        opcode = iopcode + 3;
                    } else
                    {
                        this.compileError("Unexpected promoted type \"" + type + "\"", l.getLocation());
                        opcode = iopcode;
                    }
                    this.writeOpcode(l, opcode);
                }
            } while (operands.hasNext());
            return type;
        }

        if (
            operator == "<<"  ||
            operator == ">>"  ||
            operator == ">>>"
        ) {
            final int iopcode = (
                operator == "<<"  ? Opcode.ISHL  :
                operator == ">>"  ? Opcode.ISHR  :
                operator == ">>>" ? Opcode.IUSHR : Integer.MAX_VALUE
            );

            do {
                Java.Rvalue operand = (Java.Rvalue) operands.next();

                if (type == null) {
                    type = this.compileGetValue(operand);
                } else {
                    CodeContext.Inserter convertLhsInserter = this.codeContext.newInserter();
                    IClass rhsType = this.compileGetValue(operand);

                    IClass promotedLhsType;
                    this.codeContext.pushInserter(convertLhsInserter);
                    try {
                        promotedLhsType = this.unaryNumericPromotion(l, type);
                    } finally {
                        this.codeContext.popInserter();
                    }
                    if (promotedLhsType != IClass.INT && promotedLhsType != IClass.LONG) this.compileError("Shift operation not allowed on operand type \"" + type + "\"", l.getLocation());

                    IClass promotedRhsType = this.unaryNumericPromotion(l, rhsType);
                    if (promotedRhsType != IClass.INT && promotedRhsType != IClass.LONG) this.compileError("Shift distance of type \"" + rhsType + "\" is not allowed", l.getLocation());

                    if (promotedRhsType == IClass.LONG) this.writeOpcode(l, Opcode.L2I);

                    this.writeOpcode(l, promotedLhsType == IClass.LONG ? iopcode + 1 : iopcode);
                    type = promotedLhsType;
                }
            } while (operands.hasNext());
            return type;
        }

        throw new RuntimeException("Unexpected operator \"" + operator + "\"");
    }


Generated by  Doxygen 1.6.0   Back to index