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.op;
020
021import lucee.runtime.exp.TemplateException;
022import lucee.transformer.bytecode.BytecodeContext;
023import lucee.transformer.bytecode.BytecodeException;
024import lucee.transformer.bytecode.expression.ExprDouble;
025import lucee.transformer.bytecode.expression.Expression;
026import lucee.transformer.bytecode.expression.ExpressionBase;
027import lucee.transformer.bytecode.util.Methods;
028import lucee.transformer.bytecode.util.Types;
029
030import org.objectweb.asm.Type;
031import org.objectweb.asm.commons.GeneratorAdapter;
032import org.objectweb.asm.commons.Method;
033
034public final class OpDouble extends ExpressionBase implements ExprDouble {
035
036        private static final Method DIV_REF=new Method("divRef",Types.DOUBLE,new Type[]{Types.OBJECT,Types.OBJECT});
037        private static final Method INTDIV_REF=new Method("intdivRef",Types.DOUBLE,new Type[]{Types.OBJECT,Types.OBJECT});
038        private static final Method EXP_REF=new Method("exponentRef",Types.DOUBLE,new Type[]{Types.OBJECT,Types.OBJECT});
039
040        private static final Method PLUS_REF=new Method("plusRef",Types.DOUBLE,new Type[]{Types.OBJECT,Types.OBJECT});
041        private static final Method MINUS_REF=new Method("minusRef",Types.DOUBLE,new Type[]{Types.OBJECT,Types.OBJECT});
042        private static final Method MODULUS_REF=new Method("modulusRef",Types.DOUBLE,new Type[]{Types.OBJECT,Types.OBJECT});
043        private static final Method DIVIDE_REF=new Method("divideRef",Types.DOUBLE,new Type[]{Types.OBJECT,Types.OBJECT});
044        private static final Method MULTIPLY_REF=new Method("multiplyRef",Types.DOUBLE,new Type[]{Types.OBJECT,Types.OBJECT});
045        
046        public static final int PLUS=GeneratorAdapter.ADD;
047    public static final int MINUS=GeneratorAdapter.SUB;
048    public static final int MODULUS=GeneratorAdapter.REM;
049    public static final int DIVIDE=GeneratorAdapter.DIV;
050    public static final int MULTIPLY=GeneratorAdapter.MUL;
051        public static final int EXP = 2000;
052        public static final int INTDIV = 2001;
053        
054    private int operation;
055        private Expression left;
056        private Expression right;
057    
058    OpDouble(Expression left, Expression right, int operation)  {
059        super(left.getStart(),right.getEnd());
060        this.left=      left;
061        this.right=     right;   
062        this.operation=operation;
063    }
064    
065
066        public Expression getLeft() {
067                return left;
068        }
069
070        public Expression getRight() {
071                return right;
072        }
073        
074        public int getOperation() {
075                return operation;
076        }
077    
078    /**
079     * Create a String expression from a Expression
080     * @param left 
081     * @param right 
082     * @param operation 
083     * 
084     * @return String expression
085     * @throws TemplateException 
086     */
087    public static ExprDouble toExprDouble(Expression left, Expression right,int operation)  {
088        return new OpDouble(left,right,operation);
089    }
090
091        /**
092     *
093     * @see lucee.transformer.bytecode.expression.ExpressionBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter, int)
094     */
095    public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException {
096        return writeOutDouble(bc, mode) ;
097    }
098    
099    public Type writeOutDouble(BytecodeContext bc, int mode) throws BytecodeException {
100        GeneratorAdapter adapter = bc.getAdapter();
101        
102        left.writeOut(bc,MODE_REF);
103        right.writeOut(bc,MODE_REF);
104        
105        
106        if(operation==EXP) {
107                adapter.invokeStatic(Types.OPERATOR,EXP_REF);
108        }
109        else if(operation==DIVIDE) {
110                adapter.invokeStatic(Types.OPERATOR,DIV_REF);
111        }
112        else if(operation==INTDIV) {
113                adapter.invokeStatic(Types.OPERATOR,INTDIV_REF);
114        }
115        else if(operation==PLUS) {
116                adapter.invokeStatic(Types.OPERATOR,PLUS_REF);
117        }
118        else if(operation==MINUS) {
119                adapter.invokeStatic(Types.OPERATOR,MINUS_REF);
120        }
121        else if(operation==MODULUS) {
122                adapter.invokeStatic(Types.OPERATOR,MODULUS_REF);
123        }
124        else if(operation==DIVIDE) {
125                adapter.invokeStatic(Types.OPERATOR,DIVIDE_REF);
126        }
127        else if(operation==MULTIPLY) {
128                adapter.invokeStatic(Types.OPERATOR,MULTIPLY_REF);
129        }
130        
131
132        if(mode==MODE_VALUE) {
133            adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_DOUBLE_VALUE_FROM_DOUBLE);
134            return Types.DOUBLE_VALUE;
135        }
136        
137        
138        
139        return Types.DOUBLE;
140    }
141
142}