001    package railo.transformer.bytecode.statement;
002    
003    import java.util.Stack;
004    
005    import org.objectweb.asm.Opcodes;
006    import org.objectweb.asm.commons.GeneratorAdapter;
007    
008    import railo.transformer.bytecode.BytecodeContext;
009    import railo.transformer.bytecode.BytecodeException;
010    import railo.transformer.bytecode.Statement;
011    import railo.transformer.bytecode.expression.Expression;
012    import railo.transformer.bytecode.util.ASMConstants;
013    import railo.transformer.bytecode.util.Types;
014    import railo.transformer.bytecode.visitor.TryCatchFinallyData;
015    
016    /**
017     * Return Statement
018     */
019    public final class Return extends StatementBase {
020    
021            Expression expr;
022    
023            /**
024             * Constructor of the class
025             * @param line
026             */
027            public Return(int line) {
028                    super(line);
029                    setHasFlowController(true);
030                    //expr=LitString.toExprString("", line);
031            }
032            
033            /**
034             * Constructor of the class
035             * @param expr
036             * @param line
037             */
038            public Return(Expression expr, int line) {
039                    super(line);
040                    this.expr=expr;
041                    setHasFlowController(true);
042                    //if(expr==null)expr=LitString.toExprString("", line);
043            }
044    
045            public void _writeOut(BytecodeContext bc) throws BytecodeException {
046                    GeneratorAdapter adapter = bc.getAdapter();
047                    
048                    Stack tcfs = bc.getTryCatchFinallyDataStack();
049                    int len=tcfs.size();
050                    TryCatchFinallyData data;
051                    
052                    if(expr==null)ASMConstants.NULL(adapter);
053                    else expr.writeOut(bc, Expression.MODE_REF);
054                    if(len>0) {
055                            int rtn = adapter.newLocal(Types.OBJECT);
056                            adapter.storeLocal(rtn, Types.OBJECT);
057                            for(int i=len-1;i>=0;i--) {
058                                    data=(TryCatchFinallyData) tcfs.get(i);
059                                    bc.getAdapter().visitJumpInsn(Opcodes.JSR, data.getFinallyBegin()); 
060                            }
061                            adapter.loadLocal(rtn, Types.OBJECT);
062                    }
063                    if(bc.getMethod().getReturnType().equals(Types.VOID)) {
064                            adapter.pop();
065                            adapter.visitInsn(Opcodes.RETURN);
066                    }
067                    else adapter.visitInsn(Opcodes.ARETURN);
068            }
069            
070    
071            /**
072             *
073             * @see railo.transformer.bytecode.statement.StatementBase#setParent(railo.transformer.bytecode.Statement)
074             */
075            public void setParent(Statement parent) {
076                    super.setParent(parent);
077                    parent.setHasFlowController(true);
078            }
079    }