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    }