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 {
026        
027        private Expression expr;
028        
029        private CastFloat(Expression expr) {
030            super(expr.getLine());
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.getLine());
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_REF)adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_FROM_FLOAT);
059            }
060            else if(expr instanceof ExprBoolean) {
061                expr.writeOut(bc,MODE_VALUE);
062                if(mode==MODE_VALUE)adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_VALUE_FROM_BOOLEAN);
063                else adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_FROM_BOOLEAN);
064                
065            }
066            else if(expr instanceof ExprFloat) {
067                expr.writeOut(bc,mode);
068                //if(mode==MODE_VALUE)adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_VALUE_FROM_DOUBLE);
069                //if(mode==MODE_REF) adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_FROM_FLOAT);
070            }
071            else if(expr instanceof ExprDouble) {
072                expr.writeOut(bc,MODE_VALUE);
073                if(mode==MODE_VALUE)adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_VALUE_FROM_DOUBLE);
074                else adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_FROM_DOUBLE);
075            }
076            else if(expr instanceof ExprString) {
077                expr.writeOut(bc,MODE_REF);
078                if(mode==MODE_VALUE)adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_VALUE_FROM_STRING);
079                else adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_FROM_STRING);
080            }
081            else {
082                    Type rtn = expr.writeOut(bc,mode);
083                    if(mode==MODE_VALUE) {
084                            if(!Types.isPrimitiveType(rtn)) {
085                                    adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_VALUE);
086                            }
087                            else if(Types.DOUBLE_VALUE.equals(rtn)) {
088                                    adapter.cast(Types.DOUBLE_VALUE, Types.FLOAT_VALUE);
089                            }
090                            else if(Types.FLOAT_VALUE.equals(rtn))  {}
091                            else if(Types.BOOLEAN_VALUE.equals(rtn))        {
092                                    adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_VALUE_FROM_BOOLEAN);
093                            }
094                            else {
095                                    adapter.invokeStatic(Types.CASTER,new Method("toRef",Types.toRefType(rtn),new Type[]{rtn}));
096                                    adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_VALUE);
097                            }
098                            return Types.FLOAT_VALUE;
099                    }
100                    else if(Types.isPrimitiveType(rtn))     {
101                            if(Types.DOUBLE_VALUE.equals(rtn))      {
102                                    adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_FROM_DOUBLE);
103                            }
104                            else if(Types.FLOAT_VALUE.equals(rtn))  {
105                                    adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_FROM_FLOAT);
106                            }
107                            else if(Types.BOOLEAN_VALUE.equals(rtn))        {
108                                    adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT_FROM_BOOLEAN);
109                            }
110                            else {
111                                    adapter.invokeStatic(Types.CASTER,new Method("toRef",Types.toRefType(rtn),new Type[]{rtn}));
112                                    adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT);
113                            }
114                            return Types.FLOAT;
115                    }
116                    //else {
117                    if(!Types.FLOAT.equals(rtn)) adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_FLOAT);
118                    return Types.FLOAT;
119                    //}
120            }
121            
122    
123            if(mode==MODE_VALUE)return Types.FLOAT_VALUE;
124            return Types.FLOAT;
125        }
126    
127        /* *
128         * @see railo.transformer.bytecode.expression.Expression#getType()
129         * /
130        public int getType() {
131            return Types._DOUBLE;
132        }*/
133    
134    }
135    
136    
137    
138