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