001 package railo.transformer.bytecode.op; 002 003 import java.util.ArrayList; 004 import java.util.Iterator; 005 import java.util.List; 006 007 import org.objectweb.asm.Label; 008 import org.objectweb.asm.Opcodes; 009 import org.objectweb.asm.Type; 010 import org.objectweb.asm.commons.GeneratorAdapter; 011 import org.objectweb.asm.commons.Method; 012 013 import railo.runtime.op.Elvis; 014 import railo.transformer.bytecode.BytecodeContext; 015 import railo.transformer.bytecode.BytecodeException; 016 import railo.transformer.bytecode.Literal; 017 import railo.transformer.bytecode.expression.Expression; 018 import railo.transformer.bytecode.expression.ExpressionBase; 019 import railo.transformer.bytecode.expression.var.DataMember; 020 import railo.transformer.bytecode.expression.var.Member; 021 import railo.transformer.bytecode.expression.var.Variable; 022 import railo.transformer.bytecode.util.ExpressionUtil; 023 import railo.transformer.bytecode.util.Types; 024 import railo.transformer.bytecode.visitor.ArrayVisitor; 025 026 public final class OpElvis extends ExpressionBase { 027 028 029 030 private static final Type ELVIS=Type.getType(Elvis.class); 031 public static final Method INVOKE_STR = new Method( 032 "operate", 033 Types.BOOLEAN_VALUE, 034 new Type[]{Types.PAGE_CONTEXT,Types.DOUBLE_VALUE,Types.STRING_ARRAY}); 035 036 public static final Method INVOKE_KEY = new Method( 037 "operate", 038 Types.BOOLEAN_VALUE, 039 new Type[]{Types.PAGE_CONTEXT,Types.DOUBLE_VALUE,Types.COLLECTION_KEY_ARRAY}); 040 041 private Variable left; 042 private Expression right; 043 044 /** 045 * 046 * @see railo.transformer.bytecode.expression.ExpressionBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter, int) 047 */ 048 public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException { 049 GeneratorAdapter adapter = bc.getAdapter(); 050 051 Label yes = new Label(); 052 Label end = new Label(); 053 054 List<Member> members = left.getMembers(); 055 Iterator<Member> it = members.iterator(); 056 057 // to array 058 List<DataMember> list=new ArrayList<DataMember>(); 059 while(it.hasNext()){ 060 list.add((DataMember) it.next()); 061 } 062 DataMember[] arr = list.toArray(new DataMember[members.size()]); 063 064 ExpressionUtil.visitLine(bc, left.getStart()); 065 066 // public static boolean call(PageContext pc , double scope,String[] varNames) 067 // pc 068 adapter.loadArg(0); 069 // scope 070 adapter.push((double)left.getScope()); 071 //varNames 072 073 // all literal string? 074 boolean allLiteral=true; 075 for(int i=0;i<arr.length;i++){ 076 if(!(arr[i].getName() instanceof Literal)) allLiteral=false; 077 } 078 079 ArrayVisitor av=new ArrayVisitor(); 080 if(!allLiteral) { 081 // String Array 082 av.visitBegin(adapter,Types.STRING,arr.length); 083 for(int i=0;i<arr.length;i++){ 084 av.visitBeginItem(adapter, i); 085 arr[i].getName().writeOut(bc, MODE_REF); 086 av.visitEndItem(adapter); 087 } 088 } 089 else { 090 // Collection.Key Array 091 av.visitBegin(adapter,Types.COLLECTION_KEY,arr.length); 092 for(int i=0;i<arr.length;i++){ 093 av.visitBeginItem(adapter, i); 094 Variable.registerKey(bc, arr[i].getName()); 095 av.visitEndItem(adapter); 096 } 097 } 098 av.visitEnd(); 099 100 101 // allowNull 102 //adapter.push(false); 103 104 105 106 //ASMConstants.NULL(adapter); 107 108 // call IsDefined.invoke 109 adapter.invokeStatic(ELVIS, allLiteral?INVOKE_KEY:INVOKE_STR); 110 ExpressionUtil.visitLine(bc, left.getEnd()); 111 112 113 adapter.visitJumpInsn(Opcodes.IFEQ, yes); 114 115 // left 116 ExpressionUtil.visitLine(bc, left.getStart()); 117 left.writeOut(bc, MODE_REF); 118 ExpressionUtil.visitLine(bc, left.getEnd()); 119 adapter.visitJumpInsn(Opcodes.GOTO, end); 120 121 // right 122 ExpressionUtil.visitLine(bc, right.getStart()); 123 adapter.visitLabel(yes); 124 right.writeOut(bc, MODE_REF); 125 ExpressionUtil.visitLine(bc, right.getEnd()); 126 adapter.visitLabel(end); 127 128 return Types.OBJECT; 129 130 } 131 132 133 134 135 136 137 138 private OpElvis(Variable left, Expression right) { 139 super(left.getStart(),right.getEnd()); 140 this.left=left; 141 this.right=right; 142 } 143 144 145 public static Expression toExpr(Variable left, Expression right) { 146 return new OpElvis(left,right); 147 } 148 } 149