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.expression;
020
021import lucee.transformer.bytecode.BytecodeContext;
022import lucee.transformer.bytecode.BytecodeException;
023import lucee.transformer.bytecode.util.Types;
024
025import org.objectweb.asm.Label;
026import org.objectweb.asm.Opcodes;
027import org.objectweb.asm.Type;
028import org.objectweb.asm.commons.GeneratorAdapter;
029
030public class FailSafeExpression  extends ExpressionBase implements Opcodes {
031
032        private Expression expr;
033        private Expression defaultValue;
034        
035
036        
037        public FailSafeExpression(Expression expr,Expression defaultValue) {
038                super(expr.getStart(), expr.getEnd());
039                this.expr=expr;
040                this.defaultValue=defaultValue;
041        }
042
043
044        
045        @Override
046        public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException {
047                GeneratorAdapter mv = bc.getAdapter();
048                
049                int local = mv.newLocal(Types.OBJECT);
050                
051                
052                
053                {
054                        Label begin = new Label();
055                        Label onSuccess = new Label();
056                        Label onFail = new Label();
057                        Label end = new Label();
058                        
059                        mv.visitTryCatchBlock(begin, onSuccess, onFail, "java/lang/Throwable");
060                        mv.visitLabel(begin);
061                        
062                                expr.writeOut(bc, MODE_REF);
063                                mv.storeLocal(local);
064                        
065                        mv.visitLabel(onSuccess);
066                        mv.visitJumpInsn(GOTO, end);
067                        
068                        mv.visitLabel(onFail);
069                        //mv.visitVarInsn(ASTORE, 2);
070                        
071                                defaultValue.writeOut(bc, MODE_REF);
072                                mv.storeLocal(local);
073                        
074                        
075                        mv.visitLabel(end);
076                        mv.loadLocal(local);
077
078                        //mv.visitLocalVariable("e", "Ljava/lang/Throwable;", null, l4, l3, 3);
079                        
080                
081                        }
082
083                
084                
085                return Types.OBJECT;
086        }
087
088}