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 VariableArityParameters {
011      // 8.4.1
012    
013      /* The last formal parameter in a list is special; it may be a variable arity
014      parameter, indicated by an elipsis following the type.*/
015      public void VariableArityParameterDeclaration.nameCheck() {
016        super.nameCheck();
017        if(!variableArityValid())
018          error("only the last formal paramater may be of variable arity");
019      }
020    
021      eq ConstructorDecl.getParameter(int i).variableArityValid() = i == getNumParameter() - 1;
022      eq MethodDecl.getParameter(int i).variableArityValid() = i == getNumParameter() - 1;
023      eq BasicCatch.getParameter().variableArityValid() = false;
024      eq Program.getChild().variableArityValid() = false;
025    
026      inh boolean VariableArityParameterDeclaration.variableArityValid();
027    
028      /* If the last formal parameter is a variable arity parameter of type T, it is
029      considered to define a formal parameter of type T[].*/
030      eq VariableArityParameterDeclaration.type() = super.type().arrayType();
031    
032      /* The method is then a variable arity method. Otherwise, it is a fixed arity method.*/
033      syn boolean MethodDecl.isVariableArity() = getNumParameter() == 0 ? false : getParameter(getNumParameter()-1).isVariableArity();
034      syn boolean ConstructorDecl.isVariableArity() = getNumParameter() == 0 ? false : getParameter(getNumParameter()-1).isVariableArity();
035      syn boolean ParameterDeclaration.isVariableArity() = false;
036      eq VariableArityParameterDeclaration.isVariableArity() = true;
037    
038      syn ParameterDeclaration MethodDecl.lastParameter() = 
039        getParameter(getNumParameter() - 1);
040      syn boolean MethodAccess.invokesVariableArityAsArray() {
041        if(!decl().isVariableArity())
042          return false;
043        if(arity() != decl().arity())
044          return false;
045        return getArg(getNumArg()-1).type().methodInvocationConversionTo(decl().lastParameter().type());
046      }
047      syn boolean ConstructorAccess.invokesVariableArityAsArray() {
048        if(!decl().isVariableArity())
049          return false;
050        if(arity() != decl().arity())
051          return false;
052        return getArg(getNumArg()-1).type().methodInvocationConversionTo(decl().lastParameter().type());
053      }
054      syn boolean ClassInstanceExpr.invokesVariableArityAsArray() {
055        if(!decl().isVariableArity())
056          return false;
057        if(arity() != decl().arity())
058          return false;
059        return getArg(getNumArg()-1).type().methodInvocationConversionTo(decl().lastParameter().type());
060      }
061    
062    
063      syn ParameterDeclaration ConstructorDecl.lastParameter() = 
064        getParameter(getNumParameter() - 1);
065    
066      // 15.12.2
067    
068    /*
069    A method is applicable if it is either applicable by subtyping (�15.12.2.2),
070    applicable by method invocation conversion (�15.12.2.3), or it is an applicable
071    variable arity method (�15.12.2.4).
072    
073    The process of determining applicability begins by determining the potentially
074    applicable methods (�15.12.2.1). The remainder of the process is split into
075    three phases.
076    
077    The first phase (�15.12.2.2) performs overload resolution without permitting
078    boxing or unboxing conversion, or the use of variable arity method invocation.
079    If no applicable method is found during this phase then processing continues to
080    the second phase.
081    
082    The second phase (�15.12.2.3) performs overload resolution while allowing
083    boxing and unboxing, but still precludes the use of variable arity method
084    invocation. If no applicable method is found during this phase then processing
085    continues to the third phase.
086    
087    The third phase (�15.12.2.4) allows overloading to be combined with variable
088    arity methods, boxing and unboxing.
089    
090    Deciding whether a method is applicable will, in the case of generic methods
091    (�8.4.4), require that actual type arguments be determined. Actual type
092    arguments may be passed explicitly or implicitly. If they are passed
093    implicitly, they must be inferred (�15.12.2.7) from the types of the argument
094    expressions.
095    
096    If several applicable methods have been identified during one of the three
097    phases of applicability testing, then the most specific one is chosen, as
098    specified in section �15.12.2.5. See the following subsections for details.
099    */
100    
101      public void VariableArityParameterDeclaration.toString(StringBuffer s) {
102        getModifiers().toString(s);
103        getTypeAccess().toString(s);
104        s.append(" ... " + name());
105      }
106    
107      refine AnonymousClasses
108      protected List AnonymousDecl.constructorParameterList(ConstructorDecl decl) {
109        List parameterList = new List();
110        for(int i = 0; i < decl.getNumParameter(); i++) {
111          ParameterDeclaration param = decl.getParameter(i);
112          if (param instanceof VariableArityParameterDeclaration) {
113            parameterList.add(
114                new VariableArityParameterDeclaration(
115                  new Modifiers(new List()),
116                  ((ArrayDecl) param.type()).componentType().createBoundAccess(),
117                  param.name()
118                  ));
119          } else {
120            parameterList.add(
121                new ParameterDeclaration(
122                  param.type().createBoundAccess(),
123                  param.name()
124                  ));
125          }
126        }
127    
128        return parameterList;
129      }
130    
131    }