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.tag;
020
021import java.util.ArrayList;
022import java.util.Iterator;
023import java.util.List;
024
025import lucee.transformer.bytecode.BodyBase;
026import lucee.transformer.bytecode.BytecodeContext;
027import lucee.transformer.bytecode.BytecodeException;
028import lucee.transformer.bytecode.Position;
029import lucee.transformer.bytecode.Statement;
030import lucee.transformer.bytecode.cast.CastBoolean;
031import lucee.transformer.bytecode.expression.ExprBoolean;
032import lucee.transformer.bytecode.expression.Expression;
033import lucee.transformer.bytecode.util.ExpressionUtil;
034
035import org.objectweb.asm.Label;
036import org.objectweb.asm.Opcodes;
037import org.objectweb.asm.commons.GeneratorAdapter;
038
039public final class TagIf extends TagBaseNoFinal {
040
041        
042        public TagIf(Position start,Position end) {
043                super(start,end);
044        }
045
046        public void _writeOut(BytecodeContext bc) throws BytecodeException {
047                GeneratorAdapter adapter = bc.getAdapter();
048                
049                Label end = new Label();
050                List<Statement> tmp=new ArrayList<Statement>();
051                Iterator<Statement> it = getBody().getStatements().iterator();
052                Tag t;
053                Label endIf=writeOutElseIfStart(bc, this);
054                boolean hasElse=false;
055                while(it.hasNext()) {
056                        Statement stat = it.next();
057                        if(!hasElse && stat instanceof Tag) {
058                                t=(Tag) stat;
059                                
060                                if(t.getTagLibTag().getTagClassName().equals("lucee.runtime.tag.ElseIf")) {
061                                        __writeOut(bc,tmp);
062                                        writeOutElseIfEnd(adapter, endIf, end);
063                                        endIf=writeOutElseIfStart(bc,t);
064                                        continue;
065                                }
066                                else if(t.getTagLibTag().getTagClassName().equals("lucee.runtime.tag.Else")) {
067                                        __writeOut(bc,tmp);
068                                        ExpressionUtil.visitLine(bc, t.getStart());
069                                hasElse=true;
070                                        writeOutElseIfEnd(adapter, endIf, end);
071                                        continue;
072                                }
073                        }
074                        tmp.add(stat);
075                        //ExpressionUtil.writeOut(stat, bc);
076                }
077                __writeOut(bc,tmp);
078                
079                if(!hasElse)writeOutElseIfEnd(adapter, endIf, end);
080                
081                adapter.visitLabel(end);
082        }
083
084        private void __writeOut(BytecodeContext bc, List<Statement> statements) throws BytecodeException {
085                if(statements.size()>0) {
086                        BodyBase.writeOut(bc, statements);
087                        statements.clear();
088                }
089        }
090
091        private static Label writeOutElseIfStart(BytecodeContext bc, Tag tag) throws BytecodeException {
092                GeneratorAdapter adapter = bc.getAdapter();
093
094                ExprBoolean cont = CastBoolean.toExprBoolean(tag.getAttribute("condition").getValue());
095                
096                Label endIf = new Label();
097        
098                ExpressionUtil.visitLine(bc, tag.getStart());
099        cont.writeOut(bc,Expression.MODE_VALUE);
100        adapter.ifZCmp(Opcodes.IFEQ, endIf);
101        return endIf;
102        }
103        private static void writeOutElseIfEnd(GeneratorAdapter adapter, Label endIf, Label end) {
104                adapter.visitJumpInsn(Opcodes.GOTO, end);
105                adapter.visitLabel(endIf);
106        }
107}