001    package railo.transformer.bytecode.cast;
002    
003    import org.objectweb.asm.Type;
004    import org.objectweb.asm.commons.GeneratorAdapter;
005    import org.objectweb.asm.commons.Method;
006    
007    import railo.runtime.exp.TemplateException;
008    import railo.transformer.bytecode.BytecodeContext;
009    import railo.transformer.bytecode.BytecodeException;
010    import railo.transformer.bytecode.Literal;
011    import railo.transformer.bytecode.expression.ExprBoolean;
012    import railo.transformer.bytecode.expression.ExprDouble;
013    import railo.transformer.bytecode.expression.ExprFloat;
014    import railo.transformer.bytecode.expression.ExprString;
015    import railo.transformer.bytecode.expression.Expression;
016    import railo.transformer.bytecode.expression.ExpressionBase;
017    import railo.transformer.bytecode.literal.LitFloat;
018    import railo.transformer.bytecode.op.OpDouble;
019    import railo.transformer.bytecode.util.Methods;
020    import railo.transformer.bytecode.util.Types;
021    
022    /**
023     * cast a Expression to a Double
024     */
025    public final class CastFloat extends ExpressionBase implements ExprFloat,Cast {
026        
027        private Expression expr;
028        
029        private CastFloat(Expression expr) {
030            super(expr.getStart(),expr.getEnd());
031            this.expr=expr;
032        }
033        
034        /**
035         * Create a String expression from a Expression
036         * @param expr
037         * @return String expression
038         * @throws TemplateException 
039         */
040        public static ExprFloat toExprFloat(Expression expr)  {
041            if(expr instanceof ExprFloat) return (ExprFloat) expr;
042            if(expr instanceof Literal) {
043                Double dbl = ((Literal)expr).getDouble(null);
044                if(dbl!=null) return new LitFloat((float)dbl.doubleValue(),expr.getStart(),expr.getEnd());
045            }
046            return new CastFloat(expr);
047        }
048    
049        /**
050         * @see railo.transformer.bytecode.expression.Expression#_writeOut(org.objectweb.asm.commons.GeneratorAdapter, int)
051         */
052        public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException {
053    
054            GeneratorAdapter adapter = bc.getAdapter();
055    
056            if(expr instanceof OpDouble) {
057                ((OpDouble)expr).writeOutDouble(bc,MODE_VALUE);
058                if(mode==MODE_VALUE)adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_VALUE_FROM_DOUBLE);
059                else adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_FROM_DOUBLE);
060            }
061            else if(expr instanceof ExprBoolean) {
062                expr.writeOut(bc,MODE_VALUE);
063                if(mode==MODE_VALUE)adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_VALUE_FROM_BOOLEAN);
064                else adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_FROM_BOOLEAN);
065                
066            }
067            else if(expr instanceof ExprFloat) {
068                expr.writeOut(bc,mode);
069            }
070            else if(expr instanceof ExprDouble) {
071                expr.writeOut(bc,MODE_VALUE);
072                if(mode==MODE_VALUE)adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_VALUE_FROM_DOUBLE);
073                else adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_FROM_DOUBLE);
074            }
075            else if(expr instanceof ExprString) {
076                expr.writeOut(bc,MODE_REF);
077                if(mode==MODE_VALUE)adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_VALUE_FROM_STRING);
078                else adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_FROM_STRING);
079            }
080            else {
081                    Type rtn = expr.writeOut(bc,mode);
082                    if(mode==MODE_VALUE) {
083                            if(!Types.isPrimitiveType(rtn)) {
084                                    adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_VALUE);
085                            }
086                            else if(Types.DOUBLE_VALUE.equals(rtn)) {
087                                    adapter.cast(Types.DOUBLE_VALUE, Types.FLOAT_VALUE);
088                            }
089                            else if(Types.FLOAT_VALUE.equals(rtn))  {}
090                            else if(Types.BOOLEAN_VALUE.equals(rtn))        {
091                                    adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_VALUE_FROM_BOOLEAN);
092                            }
093                            else {
094                                    adapter.invokeStatic(Types.CASTER,new Method("toRef",Types.toRefType(rtn),new Type[]{rtn}));
095                                    adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_VALUE);
096                            }
097                            return Types.FLOAT_VALUE;
098                    }
099                    else if(Types.isPrimitiveType(rtn))     {
100                            if(Types.DOUBLE_VALUE.equals(rtn))      {
101                                    adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_FROM_DOUBLE);
102                            }
103                            else if(Types.FLOAT_VALUE.equals(rtn))  {
104                                    adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_FROM_FLOAT);
105                            }
106                            else if(Types.BOOLEAN_VALUE.equals(rtn))        {
107                                    adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_FROM_BOOLEAN);
108                            }
109                            else {
110                                    adapter.invokeStatic(Types.CASTER,new Method("toRef",Types.toRefType(rtn),new Type[]{rtn}));
111                                    adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT);
112                            }
113                            return Types.FLOAT;
114                    }
115                    //else {
116                    if(!Types.FLOAT.equals(rtn)) adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT);
117                    return Types.FLOAT;
118                    //}
119            }
120            
121    
122            if(mode==MODE_VALUE)return Types.FLOAT_VALUE;
123            return Types.FLOAT;
124        }
125    
126            @Override
127            public Expression getExpr() {
128                    return expr;
129            }
130    }
131    
132    
133    
134