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.statement;
020
021import lucee.transformer.bytecode.Body;
022import lucee.transformer.bytecode.BytecodeContext;
023import lucee.transformer.bytecode.BytecodeException;
024import lucee.transformer.bytecode.Position;
025import lucee.transformer.bytecode.expression.Expression;
026import lucee.transformer.bytecode.literal.LitBoolean;
027import lucee.transformer.bytecode.util.ASMUtil;
028import lucee.transformer.bytecode.util.ExpressionUtil;
029
030import org.objectweb.asm.Label;
031import org.objectweb.asm.Opcodes;
032import org.objectweb.asm.commons.GeneratorAdapter;
033
034public final class For extends StatementBaseNoFinal implements FlowControlBreak,FlowControlContinue,HasBody {
035
036        private Expression init;
037        private Expression condition;
038        private Expression update;
039        private Body body;
040        
041        //private static final int I=1;
042
043        Label beforeUpdate = new Label();
044        Label end = new Label();
045        private String label;
046        
047        
048        
049        /**
050         * Constructor of the class
051         * @param init
052         * @param condition
053         * @param update
054         * @param body
055         * @param line
056         */
057        public For(Expression init,Expression condition,Expression update,Body body,Position start, Position end, String label) {
058                super(start,end);
059                this.init=init;
060                this.condition=condition;
061                this.update=update;
062                this.body=body;
063                this.label=label;
064                body.setParent(this);
065                
066        }
067
068        @Override
069        public void _writeOut(BytecodeContext bc) throws BytecodeException {
070                GeneratorAdapter adapter = bc.getAdapter();
071                Label beforeInit = new Label();
072                Label afterInit = new Label();
073                Label afterUpdate = new Label();
074
075                ExpressionUtil.visitLine(bc, getStart());
076                adapter.visitLabel(beforeInit);
077                if(init!=null) {
078                        init.writeOut(bc, Expression.MODE_VALUE);
079                        adapter.pop();
080                }
081                adapter.visitJumpInsn(Opcodes.GOTO, afterUpdate);
082                adapter.visitLabel(afterInit);
083                
084                body.writeOut(bc);
085                
086                adapter.visitLabel(beforeUpdate);
087                //ExpressionUtil.visitLine(bc, getStartLine());
088                if(update!=null) {
089                        update.writeOut(bc, Expression.MODE_VALUE);
090                        ASMUtil.pop(adapter,update, Expression.MODE_VALUE); 
091                }
092                //ExpressionUtil.visitLine(bc, getStartLine());
093                adapter.visitLabel(afterUpdate);
094                
095                if(condition!=null)condition.writeOut(bc, Expression.MODE_VALUE);
096                else LitBoolean.TRUE.writeOut(bc, Expression.MODE_VALUE);
097                adapter.visitJumpInsn(Opcodes.IFNE, afterInit);
098                //ExpressionUtil.visitLine(bc, getEndLine());
099                adapter.visitLabel(end);
100                
101        }
102
103        @Override
104        public Label getBreakLabel() {
105                return end;
106        }
107
108        @Override
109        public Label getContinueLabel() {
110                return beforeUpdate;
111        }
112
113        @Override
114        public Body getBody() {
115                return body;
116        }
117
118        @Override
119        public String getLabel() {
120                return label;
121        }
122}