001    package railo.transformer.bytecode.op;
002    
003    import org.objectweb.asm.Opcodes;
004    import org.objectweb.asm.Type;
005    import org.objectweb.asm.commons.GeneratorAdapter;
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.cast.CastDouble;
012    import railo.transformer.bytecode.expression.ExprDouble;
013    import railo.transformer.bytecode.expression.Expression;
014    import railo.transformer.bytecode.expression.ExpressionBase;
015    import railo.transformer.bytecode.literal.LitDouble;
016    import railo.transformer.bytecode.util.Methods;
017    import railo.transformer.bytecode.util.Types;
018    
019    public final class OpNegateNumber extends ExpressionBase implements ExprDouble {
020    
021            private ExprDouble expr;
022            
023    
024            public static final int PLUS = 0;
025            public static final int MINUS = 1;
026    
027            private OpNegateNumber(Expression expr, int line) {
028            super(line);
029            this.expr=CastDouble.toExprDouble(expr);
030        }
031        
032        /**
033         * Create a String expression from a Expression
034         * @param left 
035         * @param right 
036         * 
037         * @return String expression
038         * @throws TemplateException 
039         */
040        public static ExprDouble toExprDouble(Expression expr, int line) {
041            if(expr instanceof Literal) {
042                    Double d=((Literal) expr).getDouble(null);
043                    if(d!=null) {
044                            return new LitDouble(-d.doubleValue(),line);
045                    }
046            }
047            return new OpNegateNumber(expr,line);
048        }
049        
050        public static ExprDouble toExprDouble(Expression expr, int operation, int line) {
051            if(operation==MINUS) return toExprDouble(expr, line);
052            return CastDouble.toExprDouble(expr);
053        }
054            
055            
056            /**
057             *
058             * @see railo.transformer.bytecode.expression.ExpressionBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter, int)
059             */
060            public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException {
061                    GeneratorAdapter adapter = bc.getAdapter();
062            if(mode==MODE_REF) {
063                _writeOut(bc,MODE_VALUE);
064                adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_DOUBLE_FROM_DOUBLE);
065                return Types.DOUBLE;
066            }
067            
068            expr.writeOut(bc, MODE_VALUE);
069            adapter.visitInsn(Opcodes.DNEG);
070            
071    
072            return Types.DOUBLE_VALUE;
073            }
074    }