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    }