/** * Copyright (c) 2014, the Railo Company Ltd. * Copyright (c) 2015, Lucee Assosication Switzerland * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see <http://www.gnu.org/licenses/>. * */ package lucee.transformer.bytecode.expression.var; import lucee.transformer.TransformerException; import lucee.transformer.bytecode.BytecodeContext; import lucee.transformer.bytecode.literal.Null; import lucee.transformer.bytecode.util.Types; import lucee.transformer.bytecode.visitor.ArrayVisitor; import lucee.transformer.expression.Expression; import lucee.transformer.expression.var.Variable; import org.objectweb.asm.Type; import org.objectweb.asm.commons.GeneratorAdapter; import org.objectweb.asm.commons.Method; public final class NamedArgument extends Argument { 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?name.getFactory().createLitString(varKeyUpperCase?"NULL":"null"):name; this.varKeyUpperCase=varKeyUpperCase; } @Override public Type _writeOut(BytecodeContext bc, int mode) throws TransformerException { 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=bc.getFactory().createLitString(varKeyUpperCase?str.toUpperCase():str); getFactory().registerKey(bc, VariableString.toExprString(name),false); type=KEY; } } else { getFactory().registerKey(bc, name.getFactory().toExprString(name),false); type=KEY; } //name.writeOut(bc, MODE_REF); super._writeOut(bc, MODE_REF); //bc.getAdapter().push(variableString); bc.getAdapter().invokeStatic(Types.FUNCTION_VALUE_IMPL,NEW_INSTANCE[type][form]); return Types.FUNCTION_VALUE; } @Override public Type writeOutValue(BytecodeContext bc, int mode) throws TransformerException { return super.writeOutValue(bc, mode); } /** * @return the name */ public Expression getName() { return name; } }