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}