001    package railo.transformer.bytecode.visitor;
002    
003    import org.objectweb.asm.Label;
004    import org.objectweb.asm.Opcodes;
005    import org.objectweb.asm.commons.GeneratorAdapter;
006    
007    import railo.transformer.bytecode.BytecodeContext;
008    import railo.transformer.bytecode.util.ExpressionUtil;
009    import railo.transformer.bytecode.util.Types;
010    
011    public final class ForDoubleVisitor implements Opcodes, LoopVisitor {
012    
013            public Label beforeInit=new Label();
014            public Label beforeExpr=new Label(),afterExpr=new Label();
015            public Label beforeBody=new Label(),afterBody=new Label();
016            public Label beforeUpdate=new Label(),afterUpdate=new Label();
017            public int i;
018            
019            public int visitBeforeExpression(GeneratorAdapter adapter, int start, int step, boolean isLocal) {
020                    // init
021                    adapter.visitLabel(beforeInit);
022                    forInit(adapter, start, isLocal);
023                    adapter.goTo(beforeExpr);
024                    
025                    // update
026                    adapter.visitLabel(beforeUpdate);
027                    forUpdate(adapter, step, isLocal);
028                    
029                    // expression
030                    adapter.visitLabel(beforeExpr);
031                    return i;
032            }
033    
034            public void visitAfterExpressionBeginBody(GeneratorAdapter adapter) {
035                    adapter.ifZCmp(Opcodes.IFEQ, afterBody);
036            }
037            
038            public void visitEndBody(BytecodeContext bc,int line) {
039                    bc.getAdapter().goTo(beforeUpdate);
040                    ExpressionUtil.visitLine(bc, line);
041                    bc.getAdapter().visitLabel(afterBody);
042                    //adapter.visitLocalVariable("i", "I", null, beforeInit, afterBody, i);
043            }
044    
045            
046            public void forInit(GeneratorAdapter adapter, int start, boolean isLocal) {
047                    i=adapter.newLocal(Types.DOUBLE_VALUE); 
048                    if(isLocal)adapter.loadLocal(start,Types.DOUBLE_VALUE);
049                    else adapter.push((double)start);
050                    adapter.visitVarInsn(DSTORE, i);
051            }
052            
053            public void forUpdate(GeneratorAdapter adapter, int step, boolean isLocal) {
054                    if(isLocal) {
055                            adapter.visitVarInsn(DLOAD, i);
056                            adapter.loadLocal(step);
057                            adapter.visitInsn(DADD);
058                            adapter.visitVarInsn(DSTORE, i);
059                    }
060                    else adapter.visitIincInsn(i, step);
061            }
062    
063            /**
064             *
065             * @see railo.transformer.bytecode.visitor.LoopVisitor#visitContinue(org.objectweb.asm.commons.GeneratorAdapter)
066             */
067            public void visitContinue(BytecodeContext bc) {
068                    bc.getAdapter().visitJumpInsn(Opcodes.GOTO, beforeUpdate);
069            }
070            
071            /**
072             *
073             * @see railo.transformer.bytecode.visitor.LoopVisitor#visitBreak(org.objectweb.asm.commons.GeneratorAdapter)
074             */
075            public void visitBreak(BytecodeContext bc) {
076                    bc.getAdapter().visitJumpInsn(Opcodes.GOTO, afterBody);
077            }
078    
079            /**
080             *
081             * @see railo.transformer.bytecode.visitor.LoopVisitor#getContinueLabel()
082             */
083            public Label getContinueLabel() {
084                    return beforeUpdate;
085            }
086    
087            /**
088             *
089             * @see railo.transformer.bytecode.visitor.LoopVisitor#getBreakLabel()
090             */
091            public Label getBreakLabel() {
092                    return afterBody;
093            }
094            
095    }