package railo.transformer.bytecode.expression.var; import org.objectweb.asm.Type; import org.objectweb.asm.commons.GeneratorAdapter; import org.objectweb.asm.commons.Method; import railo.runtime.type.FunctionValueImpl; import railo.transformer.bytecode.BytecodeContext; import railo.transformer.bytecode.BytecodeException; import railo.transformer.bytecode.cast.CastString; import railo.transformer.bytecode.expression.Expression; import railo.transformer.bytecode.literal.LitString; import railo.transformer.bytecode.literal.Null; import railo.transformer.bytecode.util.Types; import railo.transformer.bytecode.visitor.ArrayVisitor; public final class NamedArgument extends Argument { private static final Type TYPE_FUNCTION_VALUE=Type.getType(FunctionValueImpl.class); private static final int VALUE=0; private static final int ARRAY=1; private static final int KEY=0; private static final int STRING=1; private final static Method[][] NEW_INSTANCE = new Method[][]{ new Method[]{ new Method("newInstance",Types.FUNCTION_VALUE,new Type[]{Types.COLLECTION_KEY,Types.OBJECT}), new Method("newInstance",Types.FUNCTION_VALUE,new Type[]{Types.COLLECTION_KEY_ARRAY,Types.OBJECT}) }, new Method[]{ new Method("newInstance",Types.FUNCTION_VALUE,new Type[]{Types.STRING,Types.OBJECT}), new Method("newInstance",Types.FUNCTION_VALUE,new Type[]{Types.STRING_ARRAY,Types.OBJECT}) } }; private Expression name; private boolean varKeyUpperCase; public NamedArgument(Expression name, Expression value, String type, boolean varKeyUpperCase) { super(value,type); this.name=name instanceof Null?LitString.toExprString(varKeyUpperCase?"NULL":"null"):name; this.varKeyUpperCase=varKeyUpperCase; } @Override public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException { int form=VALUE; int type=STRING; if(name instanceof Variable && !((Variable)name).fromHash()) { GeneratorAdapter adapter = bc.getAdapter(); String[] arr = VariableString.variableToStringArray((Variable) name,true); if(arr.length>1){ form=ARRAY; ArrayVisitor av=new ArrayVisitor(); av.visitBegin(adapter,Types.STRING,arr.length); for(int y=0;y<arr.length;y++){ av.visitBeginItem(adapter, y); adapter.push(varKeyUpperCase?arr[y].toUpperCase():arr[y]); av.visitEndItem(bc.getAdapter()); } av.visitEnd(); } else { //VariableString.toExprString(name).writeOut(bc, MODE_REF); String str = VariableString.variableToString((Variable) name,true); name=LitString.toExprString(varKeyUpperCase?str.toUpperCase():str); type=Variable.registerKey(bc, VariableString.toExprString(name))?KEY:STRING; } } else { //CastString.toExprString(name).writeOut(bc, MODE_REF); type=Variable.registerKey(bc, CastString.toExprString(name))?KEY:STRING; } //name.writeOut(bc, MODE_REF); super._writeOut(bc, MODE_REF); //bc.getAdapter().push(variableString); bc.getAdapter().invokeStatic(TYPE_FUNCTION_VALUE,NEW_INSTANCE[type][form]); return Types.FUNCTION_VALUE; } @Override public Type writeOutValue(BytecodeContext bc, int mode) throws BytecodeException { return super.writeOutValue(bc, mode); } /** * @return the name */ public Expression getName() { return name; } }