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;
020
021import java.util.ArrayList;
022import java.util.List;
023
024import lucee.transformer.bytecode.BytecodeContext;
025import lucee.transformer.bytecode.BytecodeException;
026import lucee.transformer.bytecode.expression.var.DataMember;
027import lucee.transformer.bytecode.expression.var.Member;
028import lucee.transformer.bytecode.expression.var.UDF;
029import lucee.transformer.bytecode.util.ExpressionUtil;
030import lucee.transformer.bytecode.util.Types;
031
032import org.objectweb.asm.Type;
033import org.objectweb.asm.commons.GeneratorAdapter;
034import org.objectweb.asm.commons.Method;
035
036public final class ExpressionInvoker extends ExpressionBase implements Invoker {
037
038    // Object getCollection (Object,String)
039    private final static Method GET_COLLECTION = new Method("getCollection",
040                        Types.OBJECT,
041                        new Type[]{Types.OBJECT,Types.STRING}
042                        );
043    
044    // Object get (Object,String)
045    private final static Method GET = new Method("get",
046                        Types.OBJECT,
047                        new Type[]{Types.OBJECT,Types.STRING}
048                        );
049
050    // Object getFunction (Object,String,Object[])
051    private final static Method GET_FUNCTION = new Method("getFunction",
052                        Types.OBJECT,
053                        new Type[]{Types.OBJECT,Types.STRING,Types.OBJECT_ARRAY}
054                        );
055    
056    // Object getFunctionWithNamedValues (Object,String,Object[])
057    private final static Method GET_FUNCTION_WITH_NAMED_ARGS = new Method("getFunctionWithNamedValues",
058                        Types.OBJECT,
059                        new Type[]{Types.OBJECT,Types.STRING,Types.OBJECT_ARRAY}
060                        );
061        
062    
063        private Expression expr;
064        private List members=new ArrayList();
065
066        public ExpressionInvoker(Expression expr) {
067                super(expr.getStart(),expr.getEnd());
068                this.expr=expr;
069        }
070
071        public Type _writeOut(BytecodeContext bc, int mode)     throws BytecodeException {
072
073        GeneratorAdapter adapter = bc.getAdapter();
074        
075                Type rtn=Types.OBJECT;
076                int count=members.size();
077                
078                for(int i=0;i<count;i++) {
079                adapter.loadArg(0);
080                }
081        
082                expr.writeOut(bc, Expression.MODE_REF);
083                
084                for(int i=0;i<count;i++) {
085                        Member member=((Member)members.get(i));
086                
087                        // Data Member
088                        if(member instanceof DataMember)        {
089                                ((DataMember)member).getName().writeOut(bc, MODE_REF);
090                                adapter.invokeVirtual(Types.PAGE_CONTEXT,((i+1)==count)?GET:GET_COLLECTION);
091                                rtn=Types.OBJECT;
092                        }
093                        
094                        // UDF
095                        else if(member instanceof UDF) {
096                                UDF udf=(UDF) member;
097                                
098                                udf.getName().writeOut(bc, MODE_REF);
099                                ExpressionUtil.writeOutExpressionArray(bc, Types.OBJECT, udf.getArguments());
100                                
101                                adapter.invokeVirtual(Types.PAGE_CONTEXT,udf.hasNamedArgs()?GET_FUNCTION_WITH_NAMED_ARGS:GET_FUNCTION);
102                                rtn=Types.OBJECT;
103                                
104                        }
105                }
106                
107                return rtn;
108        }
109
110        /**
111         *
112         * @see lucee.transformer.bytecode.expression.Invoker#addMember(lucee.transformer.bytecode.expression.var.Member)
113         */
114        public void addMember(Member member) {
115                members.add(member);
116        }
117
118        /**
119         *
120         * @see lucee.transformer.bytecode.expression.Invoker#getMembers()
121         */
122        public List getMembers() {
123                return members;
124        }
125
126}