001    /*
002     * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered
003     * by the modified BSD License. You should have received a copy of the
004     * modified BSD license with this compiler.
005     * 
006     * Copyright (c) 2005-2008, Torbjorn Ekman
007     * All rights reserved.
008     */
009    
010    aspect VariableArityParametersCodegen {
011      /* Invocations of a variable arity method may contain more actual argument
012      expressions than formal parameters. All the actual argument expressions that do
013      not correspond to the formal parameters preceding the variable arity parameter
014      will be evaluated and the results stored into an array that will be passed to
015      the method invocation (�15.12.4.2)*/
016      refine Transformations public void MethodAccess.transformation() {
017        if(decl().isVariableArity() && !invokesVariableArityAsArray()) {
018          // arguments to normal parameters
019          List list = new List();
020          for(int i = 0; i < decl().getNumParameter() - 1; i++)
021            list.add(getArg(i).fullCopy());
022          // arguments to variable arity parameters
023          List last = new List();
024          for(int i = decl().getNumParameter() - 1; i < getNumArg(); i++)
025            last.add(getArg(i).fullCopy());
026          // build an array holding arguments
027          Access typeAccess = decl().lastParameter().type().elementType().createQualifiedAccess();
028          for(int i = 0; i < decl().lastParameter().type().dimension(); i++)
029            typeAccess = new ArrayTypeAccess(typeAccess);
030          list.add(new ArrayCreationExpr(typeAccess, new Opt(new ArrayInit(last))));
031          // replace argument list with augemented argument list
032          setArgList(list);
033        }
034        refined();
035      }
036    
037      refine Transformations public void ClassInstanceExpr.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).fullCopy());
043          // arguments to variable arity parameters
044          List last = new List();
045          for(int i = decl().getNumParameter() - 1; i < getNumArg(); i++)
046            last.add(getArg(i).fullCopy());
047          // build an array holding arguments
048          Access typeAccess = decl().lastParameter().type().elementType().createQualifiedAccess();
049          for(int i = 0; i < decl().lastParameter().type().dimension(); i++)
050            typeAccess = new ArrayTypeAccess(typeAccess);
051          list.add(new ArrayCreationExpr(typeAccess, new Opt(new ArrayInit(last))));
052          // replace argument list with augemented argument list
053          setArgList(list);
054        }
055        refined();
056      }
057    
058      refine Transformations public void ConstructorAccess.transformation() {
059        if(decl().isVariableArity() && !invokesVariableArityAsArray()) {
060          // arguments to normal parameters
061          List list = new List();
062          for(int i = 0; i < decl().getNumParameter() - 1; i++)
063            list.add(getArg(i).fullCopy());
064          // arguments to variable arity parameters
065          List last = new List();
066          for(int i = decl().getNumParameter() - 1; i < getNumArg(); i++)
067            last.add(getArg(i).fullCopy());
068          // build an array holding arguments
069          Access typeAccess = decl().lastParameter().type().elementType().createQualifiedAccess();
070          for(int i = 0; i < decl().lastParameter().type().dimension(); i++)
071            typeAccess = new ArrayTypeAccess(typeAccess);
072          list.add(new ArrayCreationExpr(typeAccess, new Opt(new ArrayInit(last))));
073          // replace argument list with augemented argument list
074          setArgList(list);
075        }
076        refined();
077      }
078    
079      public static final int Modifiers.ACC_VARARGS = 0x0080;
080    
081      /**
082       * Add the ACC_VARARGS flag for variable arity methods.
083       */
084      refine Flags eq MethodDecl.flags() {
085        int res = refined();
086        if(isVariableArity())
087          res |= Modifiers.ACC_VARARGS;
088        return res;
089      }
090    
091      /**
092       * Add the ACC_VARARGS flag for variable arity constructors.
093       */
094      refine Flags eq ConstructorDecl.flags() {
095        int res = refined();
096        if(isVariableArity())
097          res |= Modifiers.ACC_VARARGS;
098        return res;
099      }
100    }