001 /* Copyright (c) 2005-2008, Torbjorn Ekman 002 * All rights reserved. 003 * 004 * Redistribution and use in source and binary forms, with or without 005 * modification, are permitted provided that the following conditions are met: 006 * 007 * 1. Redistributions of source code must retain the above copyright notice, 008 * this list of conditions and the following disclaimer. 009 * 010 * 2. Redistributions in binary form must reproduce the above copyright notice, 011 * this list of conditions and the following disclaimer in the documentation 012 * and/or other materials provided with the distribution. 013 * 014 * 3. Neither the name of the copyright holder nor the names of its 015 * contributors may be used to endorse or promote products derived from this 016 * software without specific prior written permission. 017 * 018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 028 * POSSIBILITY OF SUCH DAMAGE. 029 */ 030 031 aspect VariableArityParametersCodegen { 032 /* Invocations of a variable arity method may contain more actual argument 033 expressions than formal parameters. All the actual argument expressions that do 034 not correspond to the formal parameters preceding the variable arity parameter 035 will be evaluated and the results stored into an array that will be passed to 036 the method invocation (�15.12.4.2)*/ 037 refine Transformations public void MethodAccess.transformation() { 038 if (decl().isVariableArity() && !invokesVariableArityAsArray()) { 039 // arguments to normal parameters 040 List list = new List(); 041 for (int i = 0; i < decl().getNumParameter() - 1; i++) { 042 list.add(getArg(i).treeCopyNoTransform()); 043 } 044 // arguments to variable arity parameters 045 List last = new List(); 046 for (int i = decl().getNumParameter() - 1; i < getNumArg(); i++) { 047 last.add(getArg(i).treeCopyNoTransform()); 048 } 049 // build an array holding arguments 050 Access typeAccess = decl().lastParameter().type().elementType().createQualifiedAccess(); 051 for (int i = 0; i < decl().lastParameter().type().dimension(); i++) { 052 typeAccess = new ArrayTypeAccess(typeAccess); 053 } 054 list.add(new ArrayCreationExpr(typeAccess, new Opt(new ArrayInit(last)))); 055 // replace argument list with augemented argument list 056 setArgList(list); 057 } 058 refined(); 059 } 060 061 refine Transformations public void ClassInstanceExpr.transformation() { 062 if (decl().isVariableArity() && !invokesVariableArityAsArray()) { 063 // arguments to normal parameters 064 List list = new List(); 065 for (int i = 0; i < decl().getNumParameter() - 1; i++) { 066 list.add(getArg(i).treeCopyNoTransform()); 067 } 068 // arguments to variable arity parameters 069 List last = new List(); 070 for (int i = decl().getNumParameter() - 1; i < getNumArg(); i++) { 071 last.add(getArg(i).treeCopyNoTransform()); 072 } 073 // build an array holding arguments 074 Access typeAccess = decl().lastParameter().type().elementType().createQualifiedAccess(); 075 for (int i = 0; i < decl().lastParameter().type().dimension(); i++) { 076 typeAccess = new ArrayTypeAccess(typeAccess); 077 } 078 list.add(new ArrayCreationExpr(typeAccess, new Opt(new ArrayInit(last)))); 079 // replace argument list with augemented argument list 080 setArgList(list); 081 } 082 refined(); 083 } 084 085 refine Transformations public void ConstructorAccess.transformation() { 086 if (decl().isVariableArity() && !invokesVariableArityAsArray()) { 087 // arguments to normal parameters 088 List list = new List(); 089 for (int i = 0; i < decl().getNumParameter() - 1; i++) { 090 list.add(getArg(i).treeCopyNoTransform()); 091 } 092 // arguments to variable arity parameters 093 List last = new List(); 094 for (int i = decl().getNumParameter() - 1; i < getNumArg(); i++) { 095 last.add(getArg(i).treeCopyNoTransform()); 096 } 097 // build an array holding arguments 098 Access typeAccess = decl().lastParameter().type().elementType().createQualifiedAccess(); 099 for (int i = 0; i < decl().lastParameter().type().dimension(); i++) { 100 typeAccess = new ArrayTypeAccess(typeAccess); 101 } 102 list.add(new ArrayCreationExpr(typeAccess, new Opt(new ArrayInit(last)))); 103 // replace argument list with augemented argument list 104 setArgList(list); 105 } 106 refined(); 107 } 108 109 public static final int Modifiers.ACC_VARARGS = 0x0080; 110 111 /** 112 * Add the ACC_VARARGS flag for variable arity methods. 113 */ 114 refine Flags eq MethodDecl.flags() { 115 int res = refined(); 116 if (isVariableArity()) { 117 res |= Modifiers.ACC_VARARGS; 118 } 119 return res; 120 } 121 122 /** 123 * Add the ACC_VARARGS flag for variable arity constructors. 124 */ 125 refine Flags eq ConstructorDecl.flags() { 126 int res = refined(); 127 if (isVariableArity()) { 128 res |= Modifiers.ACC_VARARGS; 129 } 130 return res; 131 } 132 }