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