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