001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.transformer.bytecode.expression.var; 020 021import lucee.runtime.type.FunctionValueImpl; 022import lucee.transformer.bytecode.BytecodeContext; 023import lucee.transformer.bytecode.BytecodeException; 024import lucee.transformer.bytecode.cast.CastString; 025import lucee.transformer.bytecode.expression.Expression; 026import lucee.transformer.bytecode.literal.LitString; 027import lucee.transformer.bytecode.literal.Null; 028import lucee.transformer.bytecode.util.Types; 029import lucee.transformer.bytecode.visitor.ArrayVisitor; 030 031import org.objectweb.asm.Type; 032import org.objectweb.asm.commons.GeneratorAdapter; 033import org.objectweb.asm.commons.Method; 034 035public final class NamedArgument extends Argument { 036 037 038 039 private static final Type TYPE_FUNCTION_VALUE=Type.getType(FunctionValueImpl.class); 040 private static final int VALUE=0; 041 private static final int ARRAY=1; 042 private static final int KEY=0; 043 private static final int STRING=1; 044 045 private final static Method[][] NEW_INSTANCE = new Method[][]{ 046 new Method[]{ 047 new Method("newInstance",Types.FUNCTION_VALUE,new Type[]{Types.COLLECTION_KEY,Types.OBJECT}), 048 new Method("newInstance",Types.FUNCTION_VALUE,new Type[]{Types.COLLECTION_KEY_ARRAY,Types.OBJECT}) 049 }, 050 new Method[]{ 051 new Method("newInstance",Types.FUNCTION_VALUE,new Type[]{Types.STRING,Types.OBJECT}), 052 new Method("newInstance",Types.FUNCTION_VALUE,new Type[]{Types.STRING_ARRAY,Types.OBJECT}) 053 } 054 }; 055 056 057 private Expression name; 058 private boolean varKeyUpperCase; 059 060 public NamedArgument(Expression name, Expression value, String type, boolean varKeyUpperCase) { 061 super(value,type); 062 this.name=name instanceof Null?LitString.toExprString(varKeyUpperCase?"NULL":"null"):name; 063 this.varKeyUpperCase=varKeyUpperCase; 064 } 065 066 @Override 067 public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException { 068 069 int form=VALUE; 070 int type=STRING; 071 if(name instanceof Variable && !((Variable)name).fromHash()) { 072 GeneratorAdapter adapter = bc.getAdapter(); 073 String[] arr = VariableString.variableToStringArray((Variable) name,true); 074 if(arr.length>1){ 075 form=ARRAY; 076 ArrayVisitor av=new ArrayVisitor(); 077 av.visitBegin(adapter,Types.STRING,arr.length); 078 for(int y=0;y<arr.length;y++){ 079 av.visitBeginItem(adapter, y); 080 adapter.push(varKeyUpperCase?arr[y].toUpperCase():arr[y]); 081 av.visitEndItem(bc.getAdapter()); 082 } 083 av.visitEnd(); 084 } 085 else { 086 //VariableString.toExprString(name).writeOut(bc, MODE_REF); 087 String str = VariableString.variableToString((Variable) name,true); 088 name=LitString.toExprString(varKeyUpperCase?str.toUpperCase():str); 089 Variable.registerKey(bc, VariableString.toExprString(name)); 090 type=KEY; 091 } 092 } 093 else { 094 //CastString.toExprString(name).writeOut(bc, MODE_REF); 095 Variable.registerKey(bc, CastString.toExprString(name)); 096 type=KEY; 097 098 } 099 //name.writeOut(bc, MODE_REF); 100 super._writeOut(bc, MODE_REF); 101 //bc.getAdapter().push(variableString); 102 bc.getAdapter().invokeStatic(TYPE_FUNCTION_VALUE,NEW_INSTANCE[type][form]); 103 return Types.FUNCTION_VALUE; 104 } 105 106 107 @Override 108 public Type writeOutValue(BytecodeContext bc, int mode) throws BytecodeException { 109 return super.writeOutValue(bc, mode); 110 } 111 112 113 /** 114 * @return the name 115 */ 116 public Expression getName() { 117 return name; 118 } 119}