001 package railo.transformer.bytecode.expression.var; 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.type.FunctionValueImpl; 008 import railo.transformer.bytecode.BytecodeContext; 009 import railo.transformer.bytecode.BytecodeException; 010 import railo.transformer.bytecode.cast.CastString; 011 import railo.transformer.bytecode.expression.Expression; 012 import railo.transformer.bytecode.literal.LitString; 013 import railo.transformer.bytecode.literal.Null; 014 import railo.transformer.bytecode.util.Types; 015 import railo.transformer.bytecode.visitor.ArrayVisitor; 016 017 public final class NamedArgument extends Argument { 018 019 020 021 private static final Type TYPE_FUNCTION_VALUE=Type.getType(FunctionValueImpl.class); 022 private static final int VALUE=0; 023 private static final int ARRAY=1; 024 private static final int KEY=0; 025 private static final int STRING=1; 026 027 private final static Method[][] NEW_INSTANCE = new Method[][]{ 028 new Method[]{ 029 new Method("newInstance",Types.FUNCTION_VALUE,new Type[]{Types.COLLECTION_KEY,Types.OBJECT}), 030 new Method("newInstance",Types.FUNCTION_VALUE,new Type[]{Types.COLLECTION_KEY_ARRAY,Types.OBJECT}) 031 }, 032 new Method[]{ 033 new Method("newInstance",Types.FUNCTION_VALUE,new Type[]{Types.STRING,Types.OBJECT}), 034 new Method("newInstance",Types.FUNCTION_VALUE,new Type[]{Types.STRING_ARRAY,Types.OBJECT}) 035 } 036 }; 037 038 039 private Expression name; 040 private boolean varKeyUpperCase; 041 042 public NamedArgument(Expression name, Expression value, String type, boolean varKeyUpperCase) { 043 super(value,type); 044 this.name=name instanceof Null?LitString.toExprString(varKeyUpperCase?"NULL":"null"):name; 045 this.varKeyUpperCase=varKeyUpperCase; 046 } 047 048 @Override 049 public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException { 050 051 int form=VALUE; 052 int type=STRING; 053 if(name instanceof Variable && !((Variable)name).fromHash()) { 054 GeneratorAdapter adapter = bc.getAdapter(); 055 String[] arr = VariableString.variableToStringArray((Variable) name,true); 056 if(arr.length>1){ 057 form=ARRAY; 058 ArrayVisitor av=new ArrayVisitor(); 059 av.visitBegin(adapter,Types.STRING,arr.length); 060 for(int y=0;y<arr.length;y++){ 061 av.visitBeginItem(adapter, y); 062 adapter.push(varKeyUpperCase?arr[y].toUpperCase():arr[y]); 063 av.visitEndItem(bc.getAdapter()); 064 } 065 av.visitEnd(); 066 } 067 else { 068 //VariableString.toExprString(name).writeOut(bc, MODE_REF); 069 String str = VariableString.variableToString((Variable) name,true); 070 name=LitString.toExprString(varKeyUpperCase?str.toUpperCase():str); 071 type=Variable.registerKey(bc, VariableString.toExprString(name))?KEY:STRING; 072 } 073 } 074 else { 075 //CastString.toExprString(name).writeOut(bc, MODE_REF); 076 type=Variable.registerKey(bc, CastString.toExprString(name))?KEY:STRING; 077 078 } 079 //name.writeOut(bc, MODE_REF); 080 super._writeOut(bc, MODE_REF); 081 //bc.getAdapter().push(variableString); 082 bc.getAdapter().invokeStatic(TYPE_FUNCTION_VALUE,NEW_INSTANCE[type][form]); 083 return Types.FUNCTION_VALUE; 084 } 085 086 087 @Override 088 public Type writeOutValue(BytecodeContext bc, int mode) throws BytecodeException { 089 return super.writeOutValue(bc, mode); 090 } 091 092 093 /** 094 * @return the name 095 */ 096 public Expression getName() { 097 return name; 098 } 099 }