⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 generatoradapter.java

📁 jboss规则引擎
💻 JAVA
📖 第 1 页 / 共 4 页
字号:

    /**
     * Generates the instructions to cast a numerical value from one type to
     * another.
     * 
     * @param from the type of the top stack value
     * @param to the type into which this value must be cast.
     */
    public void cast(final Type from,
                     final Type to) {
        if ( from != to ) {
            if ( from == Type.DOUBLE_TYPE ) {
                if ( to == Type.FLOAT_TYPE ) {
                    this.mv.visitInsn( Opcodes.D2F );
                } else if ( to == Type.LONG_TYPE ) {
                    this.mv.visitInsn( Opcodes.D2L );
                } else {
                    this.mv.visitInsn( Opcodes.D2I );
                    cast( Type.INT_TYPE,
                          to );
                }
            } else if ( from == Type.FLOAT_TYPE ) {
                if ( to == Type.DOUBLE_TYPE ) {
                    this.mv.visitInsn( Opcodes.F2D );
                } else if ( to == Type.LONG_TYPE ) {
                    this.mv.visitInsn( Opcodes.F2L );
                } else {
                    this.mv.visitInsn( Opcodes.F2I );
                    cast( Type.INT_TYPE,
                          to );
                }
            } else if ( from == Type.LONG_TYPE ) {
                if ( to == Type.DOUBLE_TYPE ) {
                    this.mv.visitInsn( Opcodes.L2D );
                } else if ( to == Type.FLOAT_TYPE ) {
                    this.mv.visitInsn( Opcodes.L2F );
                } else {
                    this.mv.visitInsn( Opcodes.L2I );
                    cast( Type.INT_TYPE,
                          to );
                }
            } else {
                if ( to == Type.BYTE_TYPE ) {
                    this.mv.visitInsn( Opcodes.I2B );
                } else if ( to == Type.CHAR_TYPE ) {
                    this.mv.visitInsn( Opcodes.I2C );
                } else if ( to == Type.DOUBLE_TYPE ) {
                    this.mv.visitInsn( Opcodes.I2D );
                } else if ( to == Type.FLOAT_TYPE ) {
                    this.mv.visitInsn( Opcodes.I2F );
                } else if ( to == Type.LONG_TYPE ) {
                    this.mv.visitInsn( Opcodes.I2L );
                } else if ( to == Type.SHORT_TYPE ) {
                    this.mv.visitInsn( Opcodes.I2S );
                }
            }
        }
    }

    // ------------------------------------------------------------------------
    // Instructions to do boxing and unboxing operations
    // ------------------------------------------------------------------------

    /**
     * Generates the instructions to box the top stack value. This value is
     * replaced by its boxed equivalent on top of the stack.
     * 
     * @param type the type of the top stack value.
     */
    public void box(final Type type) {
        if ( type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY ) {
            return;
        }
        if ( type == Type.VOID_TYPE ) {
            push( (String) null );
        } else {
            Type boxed = type;
            switch ( type.getSort() ) {
                case Type.BYTE :
                    boxed = GeneratorAdapter.BYTE_TYPE;
                    break;
                case Type.BOOLEAN :
                    boxed = GeneratorAdapter.BOOLEAN_TYPE;
                    break;
                case Type.SHORT :
                    boxed = GeneratorAdapter.SHORT_TYPE;
                    break;
                case Type.CHAR :
                    boxed = GeneratorAdapter.CHARACTER_TYPE;
                    break;
                case Type.INT :
                    boxed = GeneratorAdapter.INTEGER_TYPE;
                    break;
                case Type.FLOAT :
                    boxed = GeneratorAdapter.FLOAT_TYPE;
                    break;
                case Type.LONG :
                    boxed = GeneratorAdapter.LONG_TYPE;
                    break;
                case Type.DOUBLE :
                    boxed = GeneratorAdapter.DOUBLE_TYPE;
                    break;
            }
            newInstance( boxed );
            if ( type.getSize() == 2 ) {
                // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
                dupX2();
                dupX2();
                pop();
            } else {
                // p -> po -> opo -> oop -> o
                dupX1();
                swap();
            }
            invokeConstructor( boxed,
                               new Method( "<init>",
                                           Type.VOID_TYPE,
                                           new Type[]{type} ) );
        }
    }

    /**
     * Generates the instructions to unbox the top stack value. This value is
     * replaced by its unboxed equivalent on top of the stack.
     * 
     * @param type the type of the top stack value.
     */
    public void unbox(final Type type) {
        Type t = GeneratorAdapter.NUMBER_TYPE;
        Method sig = null;
        switch ( type.getSort() ) {
            case Type.VOID :
                return;
            case Type.CHAR :
                t = GeneratorAdapter.CHARACTER_TYPE;
                sig = GeneratorAdapter.CHAR_VALUE;
                break;
            case Type.BOOLEAN :
                t = GeneratorAdapter.BOOLEAN_TYPE;
                sig = GeneratorAdapter.BOOLEAN_VALUE;
                break;
            case Type.DOUBLE :
                sig = GeneratorAdapter.DOUBLE_VALUE;
                break;
            case Type.FLOAT :
                sig = GeneratorAdapter.FLOAT_VALUE;
                break;
            case Type.LONG :
                sig = GeneratorAdapter.LONG_VALUE;
                break;
            case Type.INT :
            case Type.SHORT :
            case Type.BYTE :
                sig = GeneratorAdapter.INT_VALUE;
        }
        if ( sig == null ) {
            checkCast( type );
        } else {
            checkCast( t );
            invokeVirtual( t,
                           sig );
        }
    }

    // ------------------------------------------------------------------------
    // Instructions to jump to other instructions
    // ------------------------------------------------------------------------

    /**
     * Creates a new {@link Label}.
     * 
     * @return a new {@link Label}.
     */
    public Label newLabel() {
        return new Label();
    }

    /**
     * Marks the current code position with the given label.
     * 
     * @param label a label.
     */
    public void mark(final Label label) {
        this.mv.visitLabel( label );
    }

    /**
     * Marks the current code position with a new label.
     * 
     * @return the label that was created to mark the current code position.
     */
    public Label mark() {
        final Label label = new Label();
        this.mv.visitLabel( label );
        return label;
    }

    /**
     * Generates the instructions to jump to a label based on the comparison of
     * the top two stack values.
     * 
     * @param type the type of the top two stack values.
     * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT,
     *        LE.
     * @param label where to jump if the comparison result is <tt>true</tt>.
     */
    public void ifCmp(final Type type,
                      final int mode,
                      final Label label) {
        int intOp = -1;
        int jumpMode = mode;
        switch ( mode ) {
            case GE :
                jumpMode = GeneratorAdapter.LT;
                break;
            case LE :
                jumpMode = GeneratorAdapter.GT;
                break;
        }
        switch ( type.getSort() ) {
            case Type.LONG :
                this.mv.visitInsn( Opcodes.LCMP );
                break;
            case Type.DOUBLE :
                this.mv.visitInsn( Opcodes.DCMPG );
                break;
            case Type.FLOAT :
                this.mv.visitInsn( Opcodes.FCMPG );
                break;
            case Type.ARRAY :
            case Type.OBJECT :
                switch ( mode ) {
                    case EQ :
                        this.mv.visitJumpInsn( Opcodes.IF_ACMPEQ,
                                               label );
                        return;
                    case NE :
                        this.mv.visitJumpInsn( Opcodes.IF_ACMPNE,
                                               label );
                        return;
                }
                throw new IllegalArgumentException( "Bad comparison for type " + type );
            default :
                switch ( mode ) {
                    case EQ :
                        intOp = Opcodes.IF_ICMPEQ;
                        break;
                    case NE :
                        intOp = Opcodes.IF_ICMPNE;
                        break;
                    case GE :
                        intOp = Opcodes.IF_ICMPGE;
                        break;
                    case LT :
                        intOp = Opcodes.IF_ICMPLT;
                        break;
                    case LE :
                        intOp = Opcodes.IF_ICMPLE;
                        break;
                    case GT :
                        intOp = Opcodes.IF_ICMPGT;
                        break;
                }
                this.mv.visitJumpInsn( intOp,
                                       label );
                return;
        }
        this.mv.visitJumpInsn( jumpMode,
                               label );
    }

    /**
     * Generates the instructions to jump to a label based on the comparison of
     * the top two integer stack values.
     * 
     * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT,
     *        LE.
     * @param label where to jump if the comparison result is <tt>true</tt>.
     */
    public void ifICmp(final int mode,
                       final Label label) {
        ifCmp( Type.INT_TYPE,
               mode,
               label );
    }

    /**
     * Generates the instructions to jump to a label based on the comparison of
     * the top integer stack value with zero.
     * 
     * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT,
     *        LE.
     * @param label where to jump if the comparison result is <tt>true</tt>.
     */
    public void ifZCmp(final int mode,
                       final Label label) {
        this.mv.visitJumpInsn( mode,
                               label );
    }

    /**
     * Generates the instruction to jump to the given label if the top stack
     * value is null.
     * 
     * @param label where to jump if the condition is <tt>true</tt>.
     */
    public void ifNull(final Label label) {
        this.mv.visitJumpInsn( Opcodes.IFNULL,
                               label );
    }

    /**
     * Generates the instruction to jump to the given label if the top stack
     * value is not null.
     * 
     * @param label where to jump if the condition is <tt>true</tt>.
     */
    public void ifNonNull(final Label label) {
        this.mv.visitJumpInsn( Opcodes.IFNONNULL,
                               label );
    }

    /**
     * Generates the instruction to jump to the given label.
     * 
     * @param label where to jump if the condition is <tt>true</tt>.
     */
    public void goTo(final Label label) {
        this.mv.visitJumpInsn( Opcodes.GOTO,
                               label );
    }

    /**
     * Generates a RET instruction.
     * 
     * @param local a local variable identifier, as returned by {@link #newLocal
     *        newLocal}.
     */
    public void ret(final int local) {
        this.mv.visitVarInsn( Opcodes.RET,
                              local );
    }

    /**
     * Generates the instructions for a switch statement.
     * 
     * @param keys the switch case keys.
     * @param generator a generator to generate the code for the switch cases.
     */
    public void tableSwitch(final int[] keys,
                            final TableSwitchGenerator generator) {
        float density;
        if ( keys.length == 0 ) {
            density = 0;
        } else {
            density = (float) keys.length / (keys[keys.length - 1] - keys[0] + 1);
        }
        tableSwitch( keys,
                     generator,
                     density >= 0.5f );
    }

    /**
     * Generates the instructions for a switch statement.
     * 
     * @param keys the switch case keys.
     * @param generator a generator to generate the code for the switch cases.
     * @param useTable <tt>true</tt> to use a TABLESWITCH instruction, or
     *        <tt>false</tt> to use a LOOKUPSWITCH instruction.
     */
    public void tableSwitch(final int[] keys,
                            final TableSwitchGenerator generator,
                            final boolean useTable) {
        for ( int i = 1; i < keys.length; ++i ) {
            if ( keys[i] < keys[i - 1] ) {
                throw new IllegalArgumentException( "keys must be sorted ascending" );
            }
        }
        final Label def = newLabel();
        final Label end = newLabel();
        if ( keys.length > 0 ) {
            final int len = keys.length;
            final int min = keys[0];
            final int max = keys[len - 1];
            final int range = max - min + 1;
            if ( useTable ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -