001    package railo.transformer.bytecode.statement.java;
002    
003    import org.objectweb.asm.Type;
004    import org.objectweb.asm.commons.GeneratorAdapter;
005    
006    import railo.transformer.bytecode.BytecodeContext;
007    import railo.transformer.bytecode.BytecodeException;
008    import railo.transformer.bytecode.expression.ExpressionBase;
009    import railo.transformer.bytecode.util.Types;
010    
011    public class Operation extends ExpressionBase {
012    
013            private Object left;
014            private Object right;
015            private DataBag db;
016            private int op;
017    
018            public Operation(int line,Object left, Object right,String operation, DataBag db) {
019                    super(line);
020                    this.left=left;
021                    this.right=right;
022                    this.db = db;
023                    
024                    if("plus".equals(operation))this.op=GeneratorAdapter.ADD;
025                    else if("minus".equals(operation))this.op=GeneratorAdapter.SUB;
026                    else if("divide".equals(operation))this.op=GeneratorAdapter.DIV;
027                    else if("slash".equals(operation))this.op=GeneratorAdapter.DIV;
028                    else if("star".equals(operation))this.op=GeneratorAdapter.MUL;
029                    else if("times".equals(operation))this.op=GeneratorAdapter.MUL;
030                    else if("rem".equals(operation))this.op=GeneratorAdapter.REM;
031                    else if("remainder".equals(operation))this.op=GeneratorAdapter.REM;
032                    else if("binAnd".equals(operation))this.op=GeneratorAdapter.AND;
033                    else if("and".equals(operation))this.op=GeneratorAdapter.AND;
034                    else if("binOr".equals(operation))this.op=GeneratorAdapter.OR;
035                    else if("or".equals(operation))this.op=GeneratorAdapter.OR;
036                    else throw new RuntimeException("invalid operator ["+operation+"]");
037                    
038            }
039    
040            public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException {
041                    Type l = Assign.writeOut(db,bc,null,mode,left,getLine(),false);
042                    Type r = Assign.writeOut(db,bc,null,mode,right,getLine(),false);
043                    Type t = result(l,r);
044                    
045                    bc.getAdapter().math(op,t);
046                    
047                    return t;
048            }
049    
050            public static Type result(Type left, Type right) {
051                    if(left==Types.DOUBLE_VALUE || right==Types.DOUBLE_VALUE) return Types.DOUBLE_VALUE;
052                    if(left==Types.FLOAT_VALUE || right==Types.FLOAT_VALUE) return Types.FLOAT_VALUE;
053                    if(left==Types.LONG_VALUE || right==Types.LONG_VALUE) return Types.LONG_VALUE;
054                    if(left==Types.INT_VALUE || right==Types.INT_VALUE) return Types.INT_VALUE;
055                    if(left==Types.SHORT_VALUE || right==Types.SHORT_VALUE) return Types.SHORT_VALUE;
056                    
057                    return Types.CHAR;
058            }
059    
060            public static void dup(BytecodeContext bc, Type t) {
061                    String cn=t.getClassName();
062                    if(cn.equals("long") || cn.equals("double")) bc.getAdapter().dup2();
063                    else bc.getAdapter().dup();
064            }
065            
066    }