001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.transformer.bytecode.visitor;
020
021import lucee.transformer.bytecode.BytecodeContext;
022import lucee.transformer.bytecode.Position;
023import lucee.transformer.bytecode.util.ExpressionUtil;
024import lucee.transformer.bytecode.util.Types;
025
026import org.objectweb.asm.Label;
027import org.objectweb.asm.Opcodes;
028import org.objectweb.asm.commons.GeneratorAdapter;
029
030public final class ForIntVisitor implements Opcodes, LoopVisitor {
031
032        private Label beforeInit=new Label();
033        private Label beforeExpr=new Label(),afterExpr=new Label();
034        private Label beforeBody=new Label(),afterBody=new Label();
035        private Label beforeUpdate=new Label(),afterUpdate=new Label();
036        private int i;
037        
038        public int visitBeforeExpression(GeneratorAdapter adapter, int start, int step, boolean isLocal) {
039                // init
040                adapter.visitLabel(beforeInit);
041                forInit(adapter, start, isLocal);
042                adapter.goTo(beforeExpr);
043                
044                // update
045                adapter.visitLabel(beforeUpdate);
046                forUpdate(adapter, step, isLocal);
047                
048                // expression
049                adapter.visitLabel(beforeExpr);
050                return i;
051        }
052
053        public void visitAfterExpressionBeginBody(GeneratorAdapter adapter) {
054                adapter.ifZCmp(Opcodes.IFEQ, afterBody);
055        }
056        
057        public void visitEndBody(BytecodeContext bc,Position line) {
058                bc.getAdapter().goTo(beforeUpdate);
059                ExpressionUtil.visitLine(bc, line);
060                bc.getAdapter().visitLabel(afterBody);
061                //adapter.visitLocalVariable("i", "I", null, beforeInit, afterBody, i);
062        }
063
064        
065        private void forInit(GeneratorAdapter adapter, int start, boolean isLocal) {
066                i=adapter.newLocal(Types.INT_VALUE); 
067                if(isLocal)adapter.loadLocal(start,Types.INT_VALUE);
068                else adapter.push(start);
069                adapter.visitVarInsn(ISTORE, i);
070        }
071        
072        private void forUpdate(GeneratorAdapter adapter, int step, boolean isLocal) {
073                if(isLocal) {
074                        adapter.visitVarInsn(ILOAD, i);
075                        adapter.loadLocal(step);
076                        adapter.visitInsn(IADD);
077                        adapter.visitVarInsn(ISTORE, i);
078                }
079                else adapter.visitIincInsn(i, step);
080        }
081
082        /**
083         *
084         * @see lucee.transformer.bytecode.visitor.LoopVisitor#visitContinue(org.objectweb.asm.commons.GeneratorAdapter)
085         */
086        public void visitContinue(BytecodeContext bc) {
087                bc.getAdapter().visitJumpInsn(Opcodes.GOTO, beforeUpdate);
088        }
089        
090        /**
091         *
092         * @see lucee.transformer.bytecode.visitor.LoopVisitor#visitBreak(org.objectweb.asm.commons.GeneratorAdapter)
093         */
094        public void visitBreak(BytecodeContext bc) {
095                bc.getAdapter().visitJumpInsn(Opcodes.GOTO, afterBody);
096        }
097
098        /**
099         *
100         * @see lucee.transformer.bytecode.visitor.LoopVisitor#getContinueLabel()
101         */
102        public Label getContinueLabel() {
103                return beforeUpdate;
104        }
105
106        /**
107         *
108         * @see lucee.transformer.bytecode.visitor.LoopVisitor#getBreakLabel()
109         */
110        public Label getBreakLabel() {
111                return afterBody;
112        }
113        
114}