All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.redhat.ceylon.compiler.java.codegen.Invocation Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
/*
 * Copyright Red Hat Inc. and/or its affiliates and other contributors
 * as indicated by the authors tag. All rights reserved.
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU General Public License version 2.
 * 
 * This particular file is subject to the "Classpath" exception as provided in the 
 * LICENSE file that accompanied this code.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT A
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License,
 * along with this distribution; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 */
package com.redhat.ceylon.compiler.java.codegen;

import static com.redhat.ceylon.compiler.java.codegen.AbstractTransformer.JT_COMPANION;
import static com.redhat.ceylon.compiler.java.codegen.AbstractTransformer.JT_NO_PRIMITIVES;
import static com.redhat.ceylon.compiler.java.codegen.AbstractTransformer.JT_RAW;
import static com.redhat.ceylon.compiler.java.codegen.AbstractTransformer.JT_TYPE_ARGUMENT;
import static com.redhat.ceylon.langtools.tools.javac.code.Flags.FINAL;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeMap;

import com.redhat.ceylon.compiler.java.codegen.AbstractTransformer.BoxingStrategy;
import com.redhat.ceylon.compiler.java.codegen.Strategy.DefaultParameterMethodOwner;
import com.redhat.ceylon.compiler.typechecker.analyzer.AnalyzerUtil;
import com.redhat.ceylon.compiler.typechecker.tree.Node;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.Comprehension;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.Expression;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.FunctionArgument;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.PositionalArgument;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.PositionalArgumentList;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.QualifiedTypeExpression;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.SequencedArgument;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.StaticMemberOrTypeExpression;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.Term;
import com.redhat.ceylon.langtools.tools.javac.tree.JCTree;
import com.redhat.ceylon.langtools.tools.javac.tree.JCTree.JCAnnotation;
import com.redhat.ceylon.langtools.tools.javac.tree.JCTree.JCExpression;
import com.redhat.ceylon.langtools.tools.javac.tree.JCTree.JCReturn;
import com.redhat.ceylon.langtools.tools.javac.tree.JCTree.JCStatement;
import com.redhat.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl;
import com.redhat.ceylon.langtools.tools.javac.util.List;
import com.redhat.ceylon.langtools.tools.javac.util.ListBuffer;
import com.redhat.ceylon.compiler.typechecker.tree.TreeUtil;
import com.redhat.ceylon.model.loader.JvmBackendUtil;
import com.redhat.ceylon.model.loader.NamingBase.Suffix;
import com.redhat.ceylon.model.typechecker.model.Class;
import com.redhat.ceylon.model.typechecker.model.ClassAlias;
import com.redhat.ceylon.model.typechecker.model.ClassOrInterface;
import com.redhat.ceylon.model.typechecker.model.Constructor;
import com.redhat.ceylon.model.typechecker.model.Declaration;
import com.redhat.ceylon.model.typechecker.model.Function;
import com.redhat.ceylon.model.typechecker.model.Functional;
import com.redhat.ceylon.model.typechecker.model.Interface;
import com.redhat.ceylon.model.typechecker.model.Parameter;
import com.redhat.ceylon.model.typechecker.model.ParameterList;
import com.redhat.ceylon.model.typechecker.model.Reference;
import com.redhat.ceylon.model.typechecker.model.Scope;
import com.redhat.ceylon.model.typechecker.model.Type;
import com.redhat.ceylon.model.typechecker.model.TypeDeclaration;
import com.redhat.ceylon.model.typechecker.model.TypedDeclaration;
import com.redhat.ceylon.model.typechecker.model.TypedReference;
import com.redhat.ceylon.model.typechecker.model.Value;

abstract class Invocation {

    static boolean onValueType(AbstractTransformer gen, Tree.Term primary, Declaration primaryDeclaration) {
        // don't use the value type mechanism for optimised Java arrays get/set invocations
        if (primary instanceof Tree.QualifiedMemberOrTypeExpression){
            Tree.Primary qmePrimary = ((Tree.QualifiedMemberOrTypeExpression) primary).getPrimary();
            if(qmePrimary != null 
                    && gen.isJavaArray(qmePrimary.getTypeModel())
                    && (primaryDeclaration.getName().equals("get")
                        || primaryDeclaration.getName().equals("set"))) {
                return false;
            } else {
                return ((Tree.QualifiedMemberOrTypeExpression) primary).getMemberOperator() instanceof Tree.MemberOp
                        && Decl.isValueTypeDecl(qmePrimary)
                        && (CodegenUtil.isUnBoxed(qmePrimary) || gen.isJavaArray(qmePrimary.getTypeModel()));
            }
        } else {
            return false;
        }
    }
    
    protected final AbstractTransformer gen;
    private final Node node;
    private final Tree.Term primary;
    private final Declaration primaryDeclaration;
    private final Type returnType;
    protected boolean handleBoxing;
    protected boolean unboxed;
    protected boolean erased;
    protected BoxingStrategy boxingStrategy;
    private final Tree.Primary qmePrimary;
    private final boolean onValueType;
    private boolean callable;
    
    public boolean isCallable() {
        return callable;
    }
    
    protected Invocation(AbstractTransformer gen, 
            Tree.Term primary, Declaration primaryDeclaration,
            Type returnType, Node node) {
        this.gen = gen;
        this.primary = primary;
        this.primaryDeclaration = primaryDeclaration;
        this.returnType = returnType;
        this.node = node;
        
        if (primary instanceof Tree.QualifiedMemberOrTypeExpression){
            this.qmePrimary = ((Tree.QualifiedMemberOrTypeExpression) primary).getPrimary();
        } else {
            this.qmePrimary = null;
        }
        this.onValueType = onValueType(gen, primary, primaryDeclaration)
                && (!(primary instanceof Tree.QualifiedMemberExpression) || !(((Tree.QualifiedMemberExpression)primary).getMemberOperator() instanceof Tree.SpreadOp));
    }
    
    public String toString() {
        return getClass().getName() + " of " + node;
    }
    
    Node getNode() {
        return node;
    }

    Tree.Term getPrimary() {
        return primary;
    }

    Declaration getPrimaryDeclaration() {
        return primaryDeclaration;
    }

    Type getReturnType() {
        return returnType;
    }

    Tree.Primary getQmePrimary() {
        return qmePrimary;
    }

    boolean isOnValueType() {
        return onValueType;
    }
    
    protected Type getParameterTypeForValueType(Reference producedReference, Parameter param) {
        // we need to find the interface for this method
        Type paramType = param.getModel().getReference().getFullType().getType();
        Scope paramContainer = param.getModel().getContainer();
        if(paramContainer instanceof TypedDeclaration){
            TypedDeclaration method = (TypedDeclaration) paramContainer;
            if(method.getContainer() instanceof TypeDeclaration
                    && !(method.getContainer() instanceof Constructor)){
                TypeDeclaration container = (TypeDeclaration) method.getContainer();
                Type qualifyingType = producedReference.getQualifyingType();
                if(qualifyingType != null){
                    Type supertype = qualifyingType.getSupertype(container);
                    return paramType.substitute(supertype);
                }
            }
        }
        return paramType;
    }
    

    protected boolean isParameterRaw(Parameter param){
        Type type = param.getType();
        return type == null ? false : type.isRaw();
    }
    
    protected boolean isParameterWithConstrainedTypeParameters(Parameter param) {
        return gen.hasConstrainedTypeParameters(param);
    }

    protected boolean isParameterWithDependentCovariantTypeParameters(Parameter param) {
        Type type = param.getType();
        return gen.hasDependentCovariantTypeParameters(type);
    }

    protected abstract void addReifiedArguments(ListBuffer result);
    
    public final void setUnboxed(boolean unboxed) {
        this.unboxed = unboxed;
    }

    public final void handleBoxing(boolean b) {
        handleBoxing = b;
    }
    
    public final void setErased(boolean erased) {
        this.erased = erased;
    }

    public final void setBoxingStrategy(BoxingStrategy boxingStrategy) {
        this.boxingStrategy = boxingStrategy;
    }
    
    class TransformedInvocationPrimary {
        final JCExpression expr;
        final String selector;
        TransformedInvocationPrimary(JCExpression expr, String selector) {
            this.expr = expr;
            this.selector = selector;
        }
    }
    
    protected TransformedInvocationPrimary transformPrimary(JCExpression primaryExpr,
            String selector) {
            
        if (Decl.isJavaStaticOrInterfacePrimary(getPrimary())) {
            Declaration methodOrClass = ((Tree.QualifiedMemberOrTypeExpression)getPrimary()).getDeclaration();
            if (Decl.isJavaArrayFrom(methodOrClass)) {
                JCExpression fn = gen.makeUnwrapArray(methodOrClass);
                return new TransformedInvocationPrimary(
                        fn, null);
            }
            if (methodOrClass instanceof Function
                    && getQmePrimary() instanceof Tree.BaseTypeExpression) {
                return new TransformedInvocationPrimary(gen.naming.makeName(
                        (Function)methodOrClass, Naming.NA_FQ | Naming.NA_WRAPPER_UNQUOTED), 
                        null);
            } else if (methodOrClass instanceof Class) {
                return new TransformedInvocationPrimary(
                        gen.makeJavaType(((Tree.StaticMemberOrTypeExpression)getPrimary()).getTarget().getType(), JT_NO_PRIMITIVES),
                        null);
            }
        }
        if (isMemberRefInvocation()) {
            JCExpression callable = gen.expressionGen().transformMemberReference((Tree.QualifiedMemberOrTypeExpression)getPrimary(), (Tree.MemberOrTypeExpression)getQmePrimary());
            // The callable is a Callable we generate ourselves, it can never be erased to Object so there's no need to unerase
            selector = Naming.getCallableMethodName();
            return new TransformedInvocationPrimary(callable, selector);
        }
            
        JCExpression actualPrimExpr;
        if (getPrimary() instanceof Tree.QualifiedTypeExpression
                && ((Tree.QualifiedTypeExpression)getPrimary()).getPrimary() instanceof Tree.BaseTypeExpression
                && !Decl.isConstructor(getPrimaryDeclaration())) {
            actualPrimExpr = gen.naming.makeQualifiedThis(primaryExpr);
        } else {
            actualPrimExpr = primaryExpr;
        }
         
        if (getPrimary() instanceof Tree.BaseTypeExpression) {
            Tree.BaseTypeExpression type = (Tree.BaseTypeExpression)getPrimary();
            Declaration declaration = type.getDeclaration();
            if (Strategy.generateInstantiator(declaration)) {
                if (Decl.withinInterface(declaration)) {
                    if (primaryExpr != null) {
                        // if we have some other primary then respect that
                        actualPrimExpr = primaryExpr;
                    } else {
                        // if the class being instantiated is 
                        // within a class we expect the instantiation to be
                        // accessible from `this`, so use null
                        // otherwise we must be in an companion class, so we 
                        // need to qualify the instantiator invocation with $this
                        actualPrimExpr =  type.getScope().getInheritingDeclaration(declaration) instanceof Class ? null : gen.naming.makeQuotedThis();
                    }
                } else if (declaration.isToplevel()) {
                    actualPrimExpr = null;
                }
                // if the decl is not toplevel (but the primary is a base type
                // we must be invoking a member imported from an object
                // in which case the qualifer is needed.
            }
            if (Decl.isConstructor(declaration)) {
                selector = null;
            }
        } else {
            
            if (getPrimary() instanceof Tree.QualifiedMemberOrTypeExpression) {
                Tree.QualifiedMemberOrTypeExpression type = (Tree.QualifiedMemberOrTypeExpression)getPrimary();
                Declaration declaration = type.getDeclaration();
                if (Decl.isConstructor(declaration)) {
                    Class constructedClass = Decl.getConstructedClass(declaration);
                    if (Decl.withinInterface(constructedClass)) {
                        if (Strategy.generateInstantiator(declaration)) {
                            // Stef: this is disgusting and some of that logic has to be duplicated for base member/type
                            // expressions. it reeks of special-cases that should not be
                            Interface containerInterface = (Interface)constructedClass.getContainer();
                            if(primaryExpr != null)
                                actualPrimExpr = primaryExpr;
                            else if(type.getPrimary() instanceof Tree.BaseTypeExpression
                                    // if we are within an interface impl class, access it via our $this
                                    && gen.expressionGen().needDollarThis((Tree.BaseTypeExpression)type.getPrimary()))
                                actualPrimExpr = gen.naming.makeQuotedThis();
                            else
                                // otherwise we're within a class that implements that interface,
                                // access it via our companion
                                actualPrimExpr = gen.naming.makeCompanionFieldName(containerInterface);
                        } else {
                            actualPrimExpr = null;
                        }
                    }
                }
            } else if (getPrimary() instanceof Tree.BaseMemberOrTypeExpression) {
                Tree.BaseMemberOrTypeExpression type = (Tree.BaseMemberOrTypeExpression)getPrimary();
                Declaration declaration = type.getDeclaration();
                if (Decl.isConstructor(declaration)) {
                    selector = null;
                }
            }
            if (isIndirect()) {
                if (getPrimaryDeclaration() != null
                        && (Decl.isGetter(getPrimaryDeclaration())
                                || Decl.isToplevel(getPrimaryDeclaration())
                                || (Decl.isValueOrSharedOrCapturedParam(getPrimaryDeclaration()) 
                                        && Decl.isCaptured(getPrimaryDeclaration()) 
                                        && !Decl.isLocalNotInitializer(getPrimaryDeclaration())))) {
                    // We need to invoke the getter to obtain the Callable
                    actualPrimExpr = gen.make().Apply(null, 
                            gen.naming.makeQualIdent(primaryExpr, selector), 
                            List.nil());
                } else if (selector != null) {
                    actualPrimExpr = gen.naming.makeQualIdent(primaryExpr, selector);
                } else if (getPrimaryDeclaration() == null || !((TypedDeclaration)getPrimaryDeclaration()).getType().isTypeConstructor()) {
                    actualPrimExpr = gen.naming.makeQualifiedName(primaryExpr, (TypedDeclaration)getPrimaryDeclaration(), Naming.NA_MEMBER);
                }
                actualPrimExpr = unboxCallableIfNecessary(actualPrimExpr, getPrimary());
                if (gen.isVariadicCallable(getPrimary().getTypeModel())) {
                    selector = Naming.getCallableVariadicMethodName();
                    this.callable = true;
                } else {
                    selector = Naming.getCallableMethodName();
                    this.callable = true;
                }
                // If it's indirect the primary might be erased
                actualPrimExpr = gen.expressionGen().applyErasureAndBoxing(actualPrimExpr, 
                        getPrimary().getTypeModel(),
                        getPrimary().getTypeErased(),
                        true, // boxed
                        BoxingStrategy.BOXED, 
                        getPrimary().getTypeModel(), 
                        0);
            } else if ((getPrimaryDeclaration() instanceof Function
                            && ((Function)getPrimaryDeclaration()).isParameter()// i.e. functional parameter
                            && (!JvmBackendUtil.createMethod((Function)getPrimaryDeclaration())) // not class member, or not shared/captured
                            // we may create a method, but if we're accessing it from a default parameter expression
                            // we need to access the Callable parameter, no the member method
                        || gen.expressionGen().isWithinDefaultParameterExpression(getPrimaryDeclaration().getContainer()))) {
                if (selector != null) {
                    actualPrimExpr = gen.naming.makeQualIdent(primaryExpr, selector);
                } else {
                    actualPrimExpr = gen.naming.makeQualifiedName(primaryExpr, (TypedDeclaration)getPrimaryDeclaration(), Naming.NA_MEMBER);
                }
                actualPrimExpr = unboxCallableIfNecessary(actualPrimExpr, getPrimary());
                if (gen.isVariadicCallable(getPrimary().getTypeModel())) {
                    selector = Naming.getCallableVariadicMethodName();
                    this.callable = true;
                } else {
                    selector = Naming.getCallableMethodName();
                    this.callable = true;
                }
            }
        }
        
        return new TransformedInvocationPrimary(actualPrimExpr, selector);
    }

    protected JCExpression unboxCallableIfNecessary(JCExpression actualPrimExpr, Tree.Term primary) {
        Type primaryModel = primary.getTypeModel();
        if (gen.willEraseToObject(primaryModel)) {
            actualPrimExpr = gen.make().TypeCast(gen.makeQuotedQualIdentFromString("ceylon.language.Callable"), actualPrimExpr);
        }
        return actualPrimExpr;
    }

    boolean isMemberRefInvocation() {
        return false;
    }
    
    public boolean isIndirect() {
        return false;
    }

    public void location(CallBuilder callBuilder) {
        callBuilder.location(getNode());
    }

    public boolean isUnknownArguments() {
        return false;
    }

    public Constructor getConstructor() {
        Declaration primaryDeclaration = getPrimaryDeclaration();
        return getConstructorFromPrimary(primaryDeclaration);
    }

    protected Constructor getConstructorFromPrimary(
            Declaration primaryDeclaration) {
        if (Decl.isConstructor(primaryDeclaration)) {
            primaryDeclaration = Decl.getConstructor(primaryDeclaration);
        }
        if (primaryDeclaration instanceof Constructor) {
            return (Constructor)primaryDeclaration;
        } else if (primaryDeclaration instanceof ClassAlias) {
            TypeDeclaration aliasCtor = ((ClassAlias) primaryDeclaration).getConstructor();
            while (aliasCtor instanceof ClassAlias) {
                aliasCtor = ((ClassAlias) aliasCtor).getConstructor();
            }
            if (aliasCtor instanceof Constructor) {
                return (Constructor)aliasCtor;
            } else {
                return null;
            }
        } else if (primaryDeclaration instanceof Class
                && Decl.getDefaultConstructor((Class)primaryDeclaration) != null) {
            return Decl.getDefaultConstructor((Class)primaryDeclaration);
        } else {
            return null;
        }
    }
    

    protected boolean erasedArgument(Tree.Term expr) {
        // technically expr.getTypeErased() is all we need
        // but it usually results in unnecessary casting of null
        // the exception to that is if and switch expressions
        // with all branches being null.
        return expr.getTypeErased()
                && gen.isNullValue(expr.getTypeModel())
                && (expr instanceof Tree.SwitchExpression
                        ||expr instanceof Tree.IfExpression);
    }
}

abstract class SimpleInvocation extends Invocation {

    public SimpleInvocation(AbstractTransformer gen, Tree.Term primary,
            Declaration primaryDeclaration, Type returnType, Node node) {
        super(gen, primary, primaryDeclaration, returnType, node);
    }

    protected abstract boolean isParameterVariadicStar(int argIndex);
    protected abstract boolean isParameterVariadicPlus(int argIndex);
    
    protected final boolean isParameterSequenced(int argIndex) {
        return isParameterVariadicStar(argIndex) || isParameterVariadicPlus(argIndex);
    }

    protected final boolean isParameterJavaVariadic(int argIndex) {
        return isParameterSequenced(argIndex) && isJavaVariadicMethod();
    }

    protected abstract Type getParameterType(int argIndex);

    //protected abstract String getParameterName(int argIndex);
    protected abstract JCExpression getParameterExpression(int argIndex);

    protected abstract boolean isArgumentComprehension(int argIndex);

    protected abstract boolean getParameterUnboxed(int argIndex);
    protected abstract boolean getParameterSmall(int argIndex);

    protected abstract BoxingStrategy getParameterBoxingStrategy(int argIndex);

    protected abstract boolean hasParameter(int argIndex);

    // to be overridden
    public boolean isParameterCoerced(int argIndex) {
        return false;
    }

    // to be overridden
    protected boolean isParameterRaw(int argIndex) {
        return false;
    }

    // to be overridden
    protected boolean isParameterWithConstrainedTypeParameters(int argIndex) {
        return false;
    }

    // to be overridden
    protected boolean isParameterWithDependentCovariantTypeParameters(int argIndex) {
        return false;
    }

    /** Gets the number of arguments actually being supplied */
    protected abstract int getNumArguments();

    /** Gets the number of parameters that are available */
    protected abstract int getNumParameters();

    /**
     * Gets the transformed expression supplying the argument value for the 
     * given argument index
     */
    //protected abstract JCExpression getTransformedArgumentExpression(int argIndex);

    protected abstract boolean isSpread();
    protected abstract boolean isArgumentSpread(int argIndex);

    /**
     * For subclasses if the target method doesn't support default values for variadic
     * using overloading.
     */
    protected boolean requiresEmptyForVariadic() {
        return false;
    }

    protected boolean isJavaVariadicMethod() {
        if(isJavaMethod())
            return true;
        if(getPrimaryDeclaration() instanceof Function) {
            Declaration refinedDeclaration = JvmBackendUtil.getTopmostRefinedDeclaration(getPrimaryDeclaration());
            // variadic params are not propagated to constructors
            if(refinedDeclaration instanceof Function)
                return gen.isJavaMethod((Function) refinedDeclaration);
        }
        return false;
    }
    
    private boolean isJavaMethod() {
        if(getPrimaryDeclaration() instanceof Function) {
            return gen.isJavaMethod((Function) getPrimaryDeclaration());
        } else if (getPrimaryDeclaration() instanceof Class) {
            return gen.isJavaCtor((Class) getPrimaryDeclaration());
        }
        return false;
    }

    protected abstract Tree.Expression getArgumentExpression(int argIndex);
    protected Type getArgumentType(int argIndex) {
        return getArgumentExpression(argIndex).getTypeModel();
    }
    
    protected abstract JCExpression getTransformedArgumentExpression(int argIndex);
    
}

/**
 * Generates calls to Callable methods. This is for regular {@code Callable} objects and not
 * functional parameters, which have more info like parameter names and default values.
 */
class IndirectInvocation extends SimpleInvocation {

    private final java.util.List parameterTypes;
    private final java.util.List argumentExpressions;
    private final Comprehension comprehension;
    private final boolean variadic;
    private final boolean spread;
    private final boolean unknownArguments;

    public IndirectInvocation(
            AbstractTransformer gen, 
            Tree.Term primary,
            Declaration primaryDeclaration,
            Tree.InvocationExpression invocation) {
        super(gen, primary, primaryDeclaration, invocation.getTypeModel(), invocation);

        Type callableType = primary.getTypeModel();

        this.unknownArguments = gen.isUnknownArgumentsCallable(callableType);
        
        final java.util.List parameterTypes;
        // if we have an unknown parameter list, like Callble, we can't look at parameter types
        // note that ATM the typechecker only allows a single argument to be passed in spread form in this
        // case so we don't need to look at parameter types
        if(!this.unknownArguments){
            // find the parameter types
            final java.util.List tas = new ArrayList<>();
            tas.add(gen.getReturnTypeOfCallable(callableType));
            for (int ii = 0, l = gen.getNumParametersOfCallable(callableType); ii < l; ii++) {
                tas.add(gen.getParameterTypeOfCallable(callableType, ii));
            }
            this.variadic = gen.isVariadicCallable(callableType);
            //final java.util.List tas = primary.getTypeModel().getTypeArgumentList();
            parameterTypes = tas.subList(1, tas.size());
        }else{
            this.variadic = false; // we don't know
            parameterTypes = Collections.emptyList();
        }
        
        PositionalArgumentList positionalArgumentList = invocation.getPositionalArgumentList();
        final java.util.List argumentExpressions = new ArrayList(positionalArgumentList.getPositionalArguments().size());
        boolean spread = false;
        Comprehension comprehension = null;
        for (Tree.PositionalArgument argument : positionalArgumentList.getPositionalArguments()) {
            if(argument instanceof Tree.ListedArgument)
                argumentExpressions.add(((Tree.ListedArgument)argument).getExpression());
            else if(argument instanceof Tree.SpreadArgument){
                argumentExpressions.add(((Tree.SpreadArgument)argument).getExpression());
                spread = true;
            }else{
                comprehension = (Comprehension) argument;
            }

        }
        this.spread = spread;
        this.comprehension = comprehension;
        this.argumentExpressions = argumentExpressions;
        this.parameterTypes = parameterTypes;
    }
    
    @Override
    public boolean isIndirect() {
        return true;
    }
    
    @Override
    boolean isMemberRefInvocation() {
        return CodegenUtil.isMemberReferenceInvocation((Tree.InvocationExpression)getNode());
    }
    
    @Override
    public int getNumParameters() {
        return parameterTypes.size();
    }
    
    @Override
    protected void addReifiedArguments(ListBuffer result) {
        // can never be parameterised
    }

    @Override
    protected boolean isParameterVariadicStar(int argIndex) {
        return variadic && argIndex >= parameterTypes.size() - 1;
    }
    
    @Override
    protected boolean isParameterVariadicPlus(int argIndex) {
        return variadic && argIndex >= parameterTypes.size() - 1;
    }

    @Override
    protected Type getParameterType(int argIndex) {
        // in the Java code, all Callable.call() params are of type Object so let's not
        // pretend they are typed, this saves a lot of casting.
        // except for sequenced parameters where we do care about the iterated type
        if(isParameterSequenced(argIndex)){
            if (isArgumentSpread(argIndex) 
                    && isParameterVariadicPlus(argIndex)) {
                // We might end up calling Util.sequentialInstance to handle 
                // the spread and if the spread argument is empty, we need to 
                // transform it to something of sequential type so we can 
                // call sequentialInstance(). 
                // No worries if we don't end up calling sequentialInstance(), 
                // because the call it indirect, so not type-safe at the Java level anyway
                return gen.typeFact().getSequentialType(gen.typeFact().getIteratedType(parameterTypes.get(parameterTypes.size()-1)));
            } else {
                return parameterTypes.get(parameterTypes.size()-1);
            }
        }
        return gen.typeFact().getObjectType();
    }

    @Override
    protected JCExpression getParameterExpression(int argIndex) {
        return gen.naming.makeQuotedIdent("arg" + argIndex);
    }

    @Override
    protected boolean getParameterUnboxed(int argIndex) {
        return false;
    }

    @Override
    protected BoxingStrategy getParameterBoxingStrategy(int argIndex) {
        return BoxingStrategy.BOXED;
    }
    
    @Override
    protected boolean getParameterSmall(int argIndex) {
        return false;
    }

    @Override
    protected boolean hasParameter(int argIndex) {
        return true;
    }

    @Override
    protected int getNumArguments() {
        return argumentExpressions.size() + (comprehension != null ? 1 : 0);
    }

    @Override
    protected boolean isSpread() {
        return comprehension != null || spread;
    }

    @Override
    public boolean isUnknownArguments(){
        return unknownArguments;
    }
    
    @Override
    protected boolean isArgumentSpread(int argIndex) {
        if(spread) // spread args must be last argument
            return argIndex == argumentExpressions.size() - 1;
        if(comprehension != null) // comprehension must be last
            return argIndex == argumentExpressions.size();
        return false;
    }
    
    @Override
    protected boolean isArgumentComprehension(int argIndex){
        // comprehensions are listed as last argument after all argumentExpressions
        return comprehension != null && argIndex == argumentExpressions.size();
    }
    
    @Override
    protected Tree.Expression getArgumentExpression(int argIndex) {
        return argumentExpressions.get(argIndex);
    }
    
    @Override
    protected Type getArgumentType(int argIndex) {
        if (argIndex == argumentExpressions.size() && comprehension != null) {   
            return gen.typeFact().getSequentialType(comprehension.getTypeModel());
        }
        return super.getArgumentType(argIndex);
    }
    
    @Override
    protected JCExpression getTransformedArgumentExpression(int argIndex) {
        if (argIndex == argumentExpressions.size() && comprehension != null) {
            Type type = getParameterType(argIndex);
            return gen.expressionGen().comprehensionAsSequential(comprehension, type); 
        }
        Tree.Expression expr = getArgumentExpression(argIndex);
        if (expr.getTerm() instanceof FunctionArgument) {
            FunctionArgument farg = (FunctionArgument)expr.getTerm();
            return gen.expressionGen().transform(farg, getParameterType(argIndex));
        }
        return gen.expressionGen().transformArg(this, argIndex);
    }
    
    @Override
    public void location(CallBuilder callBuilder) {
        callBuilder.location(((Tree.InvocationExpression)getNode()).getPositionalArgumentList());
    }

}

/**
 * An abstract implementation of InvocationBuilder support invocation 
 * via positional arguments. Supports with sequenced arguments but not 
 * defaulted arguments.
 */
abstract class DirectInvocation extends SimpleInvocation {

    private final Reference producedReference;

    protected DirectInvocation(
            AbstractTransformer gen,
            Tree.Term primary,
            Declaration primaryDeclaration,
            Reference producedReference, Type returnType, 
            Node node) {
        super(gen, primary, primaryDeclaration, returnType, node);
        this.producedReference = producedReference;
    }

    protected Reference appliedReference() {
        return producedReference;
    }

    /**
     * Gets the Parameter corresponding to the given argument
     * @param argIndex
     * @return
     */
    protected abstract Parameter getParameter(int argIndex);
    
    @Override
    protected boolean isParameterVariadicStar(int argIndex) {
        return getParameter(argIndex).isSequenced() && !getParameter(argIndex).isAtLeastOne();
    }
    
    @Override
    protected boolean isParameterVariadicPlus(int argIndex) {
        return getParameter(argIndex).isSequenced() && getParameter(argIndex).isAtLeastOne();
    }
    
    @Override
    protected Type getParameterType(int argIndex) {
        int flags = AbstractTransformer.TP_TO_BOUND;
        if(isParameterSequenced(argIndex)
                && isJavaVariadicMethod()
                && isSpread())
            flags |= AbstractTransformer.TP_SEQUENCED_TYPE;
        return gen.expressionGen().getTypeForParameter(getParameter(argIndex), appliedReference(), flags);
    }
    
    @Override
    protected JCExpression getParameterExpression(int argIndex) {
        return gen.naming.makeName(getParameter(argIndex).getModel(), Naming.NA_MEMBER);
    }
    
    @Override
    protected boolean getParameterUnboxed(int argIndex) {
        return getParameter(argIndex).getModel().getUnboxed();
    }
    
    @Override
    protected BoxingStrategy getParameterBoxingStrategy(int argIndex) {
        Parameter param = getParameter(argIndex);
        if (isOnValueType() && Decl.isValueTypeDecl(getParameterTypeForValueType(producedReference, param))) {
            return BoxingStrategy.UNBOXED;
        }
        return CodegenUtil.getBoxingStrategy(param.getModel());
    }
    
    @Override
    protected boolean getParameterSmall(int argIndex) {
        Parameter param = getParameter(argIndex);
        return Decl.isSmall(param.getModel());
    }
    
    @Override
    protected boolean hasParameter(int argIndex) {
        return getParameter(argIndex) != null;
    }
    
    @Override
    protected void addReifiedArguments(ListBuffer result) {
        if (getPrimary().getTypeModel().isTypeConstructor()) {
            addTypeConstructorArguments(getPrimary().getTypeModel().getTypeArgumentList(), result);
        } else {
            addReifiedArguments(gen, producedReference, result);
        }
    }
    
    private void addTypeConstructorArguments(
            java.util.List typeArgumentList,
            ListBuffer result) {
        int ii = 0;
        for(Type reifiedTypeArg : typeArgumentList)
            result.append(new ExpressionAndType(
                    gen.make().Indexed(
                            gen.makeUnquotedIdent("applied"),
                            gen.make().Literal(ii++)), 
                    gen.makeTypeDescriptorType()));
    }

    static void addReifiedArguments(AbstractTransformer gen, Reference producedReference, ListBuffer result) {
        java.util.List reifiedTypeArgs = gen.makeReifiedTypeArguments(producedReference);
        for(JCExpression reifiedTypeArg : reifiedTypeArgs)
            result.append(new ExpressionAndType(reifiedTypeArg, gen.makeTypeDescriptorType()));
    }
}

/**
 * InvocationBuilder used for 'normal' method and initializer invocations via 
 * positional arguments. Supports sequenced and defaulted arguments.
 */
class PositionalInvocation extends DirectInvocation {

    private final Tree.PositionalArgumentList positional;
    private final java.util.List parameters;

    public PositionalInvocation(
            AbstractTransformer gen, 
            Tree.Term primary,
            Declaration primaryDeclaration,
            Reference producedReference, Tree.InvocationExpression invocation,
            java.util.List parameters) {
        super(gen, primary, unfake(primaryDeclaration), unfake(producedReference), invocation.getTypeModel(), invocation);
        positional = invocation.getPositionalArgumentList();
        this.parameters = parameters;
    }
    private static Declaration unfake(Declaration primaryDeclaration) {
        if(primaryDeclaration.isCoercionPoint()){
            if(primaryDeclaration instanceof Function)
                return ((Function)primaryDeclaration).getRealFunction();
            return ((Class)primaryDeclaration).getRealClass();
        }
        return primaryDeclaration;
    }
    private static Reference unfake(Reference producedReference) {
        Declaration declaration = producedReference.getDeclaration();
        if(declaration.isCoercionPoint()){
            if(declaration instanceof Function){
                Function realFunction = ((Function)declaration).getRealFunction();
                return realFunction.appliedTypedReference(producedReference.getQualifyingType(), producedReference.getTypeArgumentList());
            }else{
                Class realClass = ((Class)declaration).getRealClass();
                return realClass.appliedType(producedReference.getQualifyingType(), producedReference.getTypeArgumentList());
            }
        }
        return producedReference;
    }
    java.util.List getParameters() {
        return parameters;
    }
    Tree.PositionalArgumentList getPositional() {
        return positional;
    }
    @Override
    protected Tree.Expression getArgumentExpression(int argIndex) {
        PositionalArgument arg = getPositional().getPositionalArguments().get(argIndex);
        if(arg instanceof Tree.ListedArgument)
            return ((Tree.ListedArgument) arg).getExpression();
        if(arg instanceof Tree.SpreadArgument)
            return ((Tree.SpreadArgument) arg).getExpression();
        throw new BugException("argument expression is " + arg.getNodeType());
    }
    
    @Override
    protected boolean isArgumentComprehension(int argIndex){
        PositionalArgument arg = getPositional().getPositionalArguments().get(argIndex);
        return arg instanceof Tree.Comprehension;
    }
    
    @Override
    protected Type getArgumentType(int argIndex) {
        PositionalArgument arg = getPositional().getPositionalArguments().get(argIndex);
        if (arg instanceof Tree.Comprehension) {
            return gen.typeFact().getSequentialType(arg.getTypeModel());
        }
        return arg.getTypeModel();
    }
    @Override
    protected JCExpression getTransformedArgumentExpression(int argIndex) {
        PositionalArgument arg = getPositional().getPositionalArguments().get(argIndex);
        // FIXME: I don't like much this weird special case here
        if(arg instanceof Tree.ListedArgument){
            Tree.Expression expr = ((Tree.ListedArgument) arg).getExpression();
            if (expr.getTerm() instanceof FunctionArgument) {
                FunctionArgument farg = (FunctionArgument)expr.getTerm();
                return gen.expressionGen().transform(farg, getParameterType(argIndex));
            }
        }
        // special case for comprehensions which are not expressions
        if(arg instanceof Tree.Comprehension){
            Type type = getParameterType(argIndex);
            return gen.expressionGen().comprehensionAsSequential((Comprehension) arg, type); 
        }
        return gen.expressionGen().transformArg(this, argIndex);
    }
    @Override
    protected Parameter getParameter(int argIndex) {
        int realIndex = argIndex >= parameters.size() ? parameters.size()-1 : argIndex;
        Parameter param = parameters.get(realIndex);
        if(param.getModel().isCoercionPoint()){
            Parameter realParameter = ((Functional)getPrimaryDeclaration()).getFirstParameterList().getParameters().get(realIndex);
            return realParameter;
        }
        return param;
    }
    
    @Override
    public boolean isParameterCoerced(int argIndex) {
        // FIXME: suboptimal copy
        Parameter param = parameters.get(argIndex >= parameters.size() ? parameters.size()-1 : argIndex);
        return param.getModel().isCoercionPoint();
    }
    
    @Override
    protected int getNumArguments() {
        return getPositional().getPositionalArguments().size();
    }
    @Override
    protected int getNumParameters() {
        return parameters.size();
    }
    @Override
    protected boolean isSpread() {
        java.util.List args = getPositional().getPositionalArguments();
        if(args.isEmpty())
            return false;
        PositionalArgument last = args.get(args.size()-1);
        return last instanceof Tree.SpreadArgument || last instanceof Tree.Comprehension;
    }
    
    @Override
    protected boolean isArgumentSpread(int argIndex) {
        PositionalArgument arg = getPositional().getPositionalArguments().get(argIndex);
        return arg instanceof Tree.SpreadArgument || arg instanceof Tree.Comprehension;
    }
    
    @Override
    protected boolean isParameterRaw(int argIndex){
        return isParameterRaw(getParameter(argIndex));
    }
    
    @Override
    protected boolean isParameterWithConstrainedTypeParameters(int argIndex) {
        return isParameterWithConstrainedTypeParameters(getParameter(argIndex));
    }

    @Override
    protected boolean isParameterWithDependentCovariantTypeParameters(int argIndex) {
        return isParameterWithDependentCovariantTypeParameters(getParameter(argIndex));
    }

    protected boolean hasDefaultArgument(int ii) {
        return getParameters().get(ii).isDefaulted();
    }
    
    @Override
    public void location(CallBuilder callBuilder) {
        callBuilder.location(positional);
    }
}

/**
 * InvocationBuilder used for constructing invocations of {@code super()}
 * when creating constructors.
 */
class SuperInvocation extends PositionalInvocation {
    
    static Declaration unaliasedPrimaryDeclaration(Tree.InvocationExpression invocation) {
        Declaration declaration = ((Tree.MemberOrTypeExpression)invocation.getPrimary()).getDeclaration();
        if (declaration instanceof ClassAlias) {
            Type et = ((ClassAlias) declaration).getExtendedType();
            if (et!=null) {
                declaration = et.getDeclaration();
            }
        }
        return declaration;
    }
    
    private final ClassOrInterface sub;
    private CtorDelegation delegation;
    private boolean delegationDelegation;
    
    SuperInvocation(AbstractTransformer gen,
            ClassOrInterface sub,
            CtorDelegation delegation,
            Tree.InvocationExpression invocation,
            ParameterList parameterList, 
            boolean delegationDelegation) {
        super(gen, 
                invocation.getPrimary(), 
                unaliasedPrimaryDeclaration(invocation),
                ((Tree.MemberOrTypeExpression)invocation.getPrimary()).getTarget(),
                invocation,
                parameterList.getParameters());
        this.sub = sub;
        this.delegation = delegation;
        this.delegationDelegation = delegationDelegation;
    }
    
    CtorDelegation getDelegation() {
        return delegation;
    }
    
    ClassOrInterface getSub() {
        return sub;
    }

    @Override
    public Constructor getConstructor() {
        // For the constructor we need the possibly-aliased primary declaration
        Declaration primaryDeclaration = ((Tree.MemberOrTypeExpression)getPrimary()).getDeclaration();
        return getConstructorFromPrimary(primaryDeclaration);
    }

    public boolean isDelegationDelegation() {
        return delegationDelegation;
    }

    @Override
    protected void addReifiedArguments(ListBuffer result) {
        if (!isDelegationDelegation()) {
            super.addReifiedArguments(result);
        } else {
            addReifiedArguments(gen, sub.getReference(), result);
        }
    }
}


/**
 * InvocationBuilder for constructing the invocation of a method reference 
 * used when implementing {@code Callable.call()}.
 * 
 * This will be used when you do:
 * 

* * void f(){ * value callable = f; * } * *

* And will generate the code required to put inside the Callable's {@code $call} method to * invoke {@code f}: {@code f();}. The generation of the Callable or its methods is not done here. */ class CallableInvocation extends DirectInvocation { private final java.util.List callableParameters; private final java.util.List functionalParameters; private final int parameterCount; private boolean tempVars; private Naming.SyntheticName instanceFieldName; private boolean instanceFieldIsBoxed; private boolean isCallableToFunctionalInterfaceBridge; public CallableInvocation( AbstractTransformer gen, Naming.SyntheticName primaryName, boolean primaryIsBoxed, Tree.Term primary, Declaration primaryDeclaration, Reference producedReference, Type returnType, Tree.Term expr, ParameterList parameterList, int parameterCount, boolean tempVars) { super(gen, primary, primaryDeclaration, producedReference, returnType, expr); this.instanceFieldName = primaryName; this.instanceFieldIsBoxed = primaryIsBoxed; Functional functional = null; boolean useParameterList = false; if(primary instanceof Tree.MemberOrTypeExpression){ Declaration declaration = ((Tree.MemberOrTypeExpression) primary).getDeclaration(); if(declaration instanceof Functional) functional = (Functional) declaration; else{ // inherit params of a Callable value ref, for SAM wrapper useParameterList = true; } }else if(primary instanceof Tree.FunctionArgument) functional = ((Tree.FunctionArgument) primary).getDeclarationModel(); else if(primary instanceof Tree.InvocationExpression){ useParameterList = true; isCallableToFunctionalInterfaceBridge = true; } if(useParameterList) callableParameters = parameterList.getParameters(); else if(functional != null) callableParameters = functional.getFirstParameterList().getParameters(); else callableParameters = Collections.emptyList(); functionalParameters = parameterList.getParameters(); this.parameterCount = parameterCount; // FIXME: only do this if not Callable subtype? TypedReference samRef = gen.checkForFunctionalInterface(producedReference.getType()); if(samRef != null){ TypedDeclaration samDeclaration = samRef.getDeclaration(); setUnboxed(samDeclaration.getUnboxed()); }else{ setUnboxed(expr.getUnboxed()); } setBoxingStrategy(BoxingStrategy.BOXED);// Must be boxed because non-primitive return type handleBoxing(true); if (producedReference.getDeclaration() instanceof TypedDeclaration) { TypedDeclaration tdecl = (TypedDeclaration) producedReference.getDeclaration(); setErased(CodegenUtil.hasTypeErased(tdecl)|| CodegenUtil.hasTypeErased(primary)); } this.tempVars = tempVars; } @Override boolean isOnValueType() { return super.isOnValueType() && !instanceFieldIsBoxed; } @Override protected int getNumArguments() { return parameterCount; } @Override protected int getNumParameters() { return functionalParameters.size(); } @Override protected boolean isSpread() { return isParameterSequenced(getNumArguments() - 1); } @Override protected boolean isArgumentSpread(int argIndex) { return isSpread() && argIndex == getNumArguments() - 1; } @Override protected boolean isArgumentComprehension(int argIndex){ return true; } @Override protected JCExpression getTransformedArgumentExpression(int argIndex) { Parameter param = callableParameters.get(argIndex); // note: we don't deal with unboxing here, as that is taken care of already by CallableBuilder by unboxing the // Callable arguments into unboxed local vars if required and if it's a value type String paramName; if (tempVars) { paramName = Naming.getCallableTempVarName(param); } else if (getPrimaryDeclaration() instanceof Class && ((Class)getPrimaryDeclaration()).hasConstructors()) { paramName = Naming.getAliasedParameterName(param); } else { paramName = param.getName(); } return gen.makeUnquotedIdent(paramName); } @Override protected Parameter getParameter(int index) { return functionalParameters.get(index); } @Override protected Expression getArgumentExpression(int argIndex) { throw new BugException("I override getTransformedArgumentExpression(), so should never be called"); } @Override protected Type getArgumentType(int argIndex) { Parameter param = callableParameters.get(argIndex); return getParameterTypeForValueType(appliedReference(), param); } @Override public void location(CallBuilder callBuilder) { callBuilder.location(null); } protected TransformedInvocationPrimary transformPrimary(JCExpression primaryExpr, String selector) { JCExpression transformedPrimary = instanceFieldName != null ? instanceFieldName.makeIdent() : primaryExpr; String transformedSelector = selector; if(getPrimaryDeclaration() instanceof Value){ if(transformedPrimary == null) transformedPrimary = gen.makeUnquotedIdent(selector); else transformedPrimary = gen.makeQualIdent(primaryExpr, selector); Type primaryType = ((Value)getPrimaryDeclaration()).getType(); TypedReference samRef = gen.checkForFunctionalInterface(primaryType); if(samRef != null) transformedSelector = samRef.getDeclaration().getName(); else transformedSelector = Naming.getCallableMethodName(); }else if(getPrimaryDeclaration() instanceof Function && getPrimaryDeclaration().isParameter() // This is fishy at best && transformedPrimary == null){ // FIXME: there's a good chance this should be merged with the previous block transformedPrimary = gen.makeUnquotedIdent(selector); transformedSelector = Naming.getCallableMethodName(); }else if(isCallableToFunctionalInterfaceBridge){ transformedSelector = Naming.getCallableMethodName(); } return new TransformedInvocationPrimary(transformedPrimary, transformedSelector); } public Constructor getConstructor() { return getConstructorFromPrimary(appliedReference().getDeclaration()); } @Override protected void addReifiedArguments(ListBuffer result) { if(!isCallableToFunctionalInterfaceBridge) super.addReifiedArguments(result); } } /** * InvocationBuilder for methods specified with a method reference. This builds the specifier invocation * within the body of the specified method. * * For example for {@code void foo(); foo = f;} we generate: {@code f()} that you would then place into * the generated method for {@code foo}. */ class MethodReferenceSpecifierInvocation extends DirectInvocation { private final Function method; private boolean variadic; private java.util.List targetParameters; private java.util.List sourceParameters; public MethodReferenceSpecifierInvocation( AbstractTransformer gen, Tree.Primary primary, Declaration primaryDeclaration, Reference producedReference, Function method, Tree.SpecifierExpression node) { super(gen, primary, primaryDeclaration, producedReference, method.getType(), node); this.method = method; setUnboxed(primary.getUnboxed()); setBoxingStrategy(CodegenUtil.getBoxingStrategy(method)); this.sourceParameters = method.getFirstParameterList().getParameters(); this.targetParameters = ((Functional)getPrimaryDeclaration()).getFirstParameterList().getParameters(); this.variadic = getPrimaryDeclaration().isVariadic(); if(!targetParameters.isEmpty()){ Parameter lastParam = targetParameters.get(targetParameters.size() - 1); this.variadic |= lastParam.isSequenced(); } } @Override protected int getNumArguments() { return sourceParameters.size(); } @Override protected int getNumParameters() { return targetParameters.size(); } @Override protected JCExpression getTransformedArgumentExpression(int argIndex) { Type exprType = getArgumentType(argIndex); Parameter declaredParameter = getParameter(argIndex); Parameter declaredArgument = sourceParameters.get(argIndex); JCExpression result = gen.naming.makeName(declaredArgument.getModel(), Naming.NA_MEMBER); BoxingStrategy boxingStrategy; if(variadic){ boxingStrategy = BoxingStrategy.BOXED; }else{ boxingStrategy = CodegenUtil.getBoxingStrategy(declaredParameter.getModel()); } result = gen.expressionGen().applyErasureAndBoxing( result, exprType, !CodegenUtil.isUnBoxed(declaredArgument.getModel()), boxingStrategy, declaredParameter.getType()); return result; } @Override protected Parameter getParameter(int argIndex) { if(variadic && argIndex >= targetParameters.size()) return targetParameters.get(targetParameters.size() - 1); return targetParameters.get(argIndex); } @Override protected boolean isSpread() { return sourceParameters.get(getNumArguments() - 1).isSequenced(); } @Override protected boolean isArgumentSpread(int argIndex) { return isSpread() && argIndex == getNumArguments() - 1; } @Override protected Expression getArgumentExpression(int argIndex) { throw new BugException("I override getArgumentExpression(), so should never be called"); } @Override protected boolean isArgumentComprehension(int argIndex){ throw new BugException("I override getTransformedArgumentExpression(), so should never be called"); } @Override public void location(CallBuilder callBuilder) { callBuilder.location(null); } @Override protected Type getArgumentType(int argIndex) { Parameter param = sourceParameters.get(argIndex); return getParameterTypeForValueType(appliedReference(), param); } } /** * InvocationBuilder for methods specified eagerly with a Callable. This builds the Callable invocation * within the body of the specified method. * * For example for {@code void foo(); foo = f;} we generate: {@code f.$call()} that you would then place into * the generated method for {@code foo}. */ class CallableSpecifierInvocation extends Invocation { private final Function method; private final JCExpression callable; private final Term callableTerm; public CallableSpecifierInvocation( AbstractTransformer gen, Function method, JCExpression callableExpr, Tree.Term callableTerm, Node node) { super(gen, null, null, method.getType(), node); this.callable = callableExpr; this.callableTerm = callableTerm; this.method = method; // Because we're calling a callable, and they always return a // boxed result setUnboxed(false); setBoxingStrategy(method.getUnboxed() ? BoxingStrategy.UNBOXED : BoxingStrategy.BOXED); } @Override protected void addReifiedArguments(ListBuffer result) { // nothing required here } JCExpression getCallable() { if(callableTerm != null) return unboxCallableIfNecessary(callable, callableTerm); return callable; } Function getMethod() { return method; } } /** * InvocationBuilder for 'normal' method and initializer invocations * using named arguments. */ class NamedArgumentInvocation extends Invocation { private final Tree.NamedArgumentList namedArgumentList; private final ListBuffer vars = new ListBuffer(); private final Naming.SyntheticName callVarName; private final Naming.SyntheticName varBaseName; private final Set argNames = new HashSet(); private final TreeMap argsNamesByIndex = new TreeMap(); private final TreeMap argsAndTypes = new TreeMap(); private final Set bound = new HashSet(); private Reference producedReference; public NamedArgumentInvocation( AbstractTransformer gen, Tree.Term primary, Declaration primaryDeclaration, Reference producedReference, Tree.InvocationExpression invocation) { super(gen, primary, primaryDeclaration, invocation.getTypeModel(), invocation); this.producedReference = producedReference; namedArgumentList = invocation.getNamedArgumentList(); varBaseName = gen.naming.alias("arg"); callVarName = varBaseName.suffixedBy(Suffix.$callable$); } @Override protected void addReifiedArguments(ListBuffer result) { Reference ref = gen.resolveAliasesForReifiedTypeArguments(producedReference); if(!gen.supportsReified(ref.getDeclaration())) return; int tpCount = gen.getTypeParameters(ref).size(); for(int tpIndex = 0;tpIndex getVars() { return vars; } Iterable getArgsNamesByIndex() { return argsNamesByIndex.values(); } Iterable getArgumentsAndTypes() { return argsAndTypes.values(); } /** * Constructs the vars used in the Let expression */ private void buildVars() { if (getPrimaryDeclaration() == null) { return; } boolean prev = gen.expressionGen().withinInvocation(false); java.util.List namedArguments = namedArgumentList.getNamedArguments(); SequencedArgument sequencedArgument = namedArgumentList.getSequencedArgument(); java.util.List paramLists = ((Functional)getPrimaryDeclaration()).getParameterLists(); java.util.List declaredParams = paramLists.get(0).getParameters(); appendVarsForNamedArguments(namedArguments, declaredParams); appendVarsForReifiedTypeArguments(); if(sequencedArgument != null) appendVarsForSequencedArguments(sequencedArgument, declaredParams); boolean hasDefaulted = appendVarsForDefaulted(declaredParams); DefaultParameterMethodOwner owner = Strategy.defaultParameterMethodOwner(getPrimaryDeclaration()); if (hasDefaulted && owner != DefaultParameterMethodOwner.STATIC && owner != DefaultParameterMethodOwner.OUTER && owner != DefaultParameterMethodOwner.OUTER_COMPANION) { vars.prepend(makeThis()); } gen.expressionGen().withinInvocation(prev); } private void appendVarsForReifiedTypeArguments() { java.util.List reifiedTypeArgs = gen.makeReifiedTypeArguments(producedReference); int index = 0; for(JCExpression reifiedTypeArg : reifiedTypeArgs){ Naming.SyntheticName argName = reifiedTypeArgName(index); JCVariableDecl varDecl = gen.makeVar(argName, gen.makeTypeDescriptorType(), reifiedTypeArg); this.vars.append(varDecl); index++; } } private void appendVarsForSequencedArguments(Tree.SequencedArgument sequencedArgument, java.util.List declaredParams) { // FIXME: this is suspisciously similar to AbstractTransformer.makeIterable(java.util.List list, Type seqElemType) // and possibly needs to be merged Parameter parameter = sequencedArgument.getParameter(); Type parameterType = parameterType(parameter, parameter.getType(), gen.TP_TO_BOUND); // find out the individual type, we use the argument type for the value, and the param type for the temp variable gen.at(sequencedArgument); Type tupleType = AnalyzerUtil.getTupleType(sequencedArgument.getPositionalArguments(), gen.typeFact(), false); // we can't just generate types like Foo if the target type param is not raw because the bounds will // not match, so we go raw, we also ignore primitives naturally int flags = JT_RAW | JT_NO_PRIMITIVES; Type argumentsType; Type iteratedType; Type absentType; if (gen.typeFact().isIterableType(tupleType)) { argumentsType = tupleType.getSupertype(gen.typeFact().getIterableDeclaration()); iteratedType = gen.typeFact().getIteratedType(argumentsType); absentType = gen.typeFact().getIteratedAbsentType(argumentsType); } else if (gen.typeFact().isJavaIterableType(tupleType)) { argumentsType = tupleType.getSupertype(gen.typeFact().getJavaIterableDeclaration()); iteratedType = gen.typeFact().getJavaIteratedType(argumentsType); absentType = gen.typeFact().getNullType(); } else if (gen.typeFact().isJavaObjectArrayType(tupleType)) { argumentsType = tupleType.getSupertype(gen.typeFact().getJavaObjectArrayDeclaration()); iteratedType = gen.typeFact().getJavaArrayElementType(argumentsType); absentType = gen.typeFact().getNullType(); } else if (gen.typeFact().isJavaPrimitiveArrayType(tupleType)) { argumentsType = tupleType.getSupertype(gen.typeFact().getJavaObjectArrayDeclaration()); iteratedType = gen.typeFact().getJavaArrayElementType(tupleType); absentType = gen.typeFact().getNullType(); } else { throw BugException.unhandledTypeCase(tupleType); } JCTree.JCExpression sequenceValue; if (Strategy.useConstantIterable(sequencedArgument)) { sequenceValue = gen.makeConstantIterable(sequencedArgument, iteratedType, absentType, flags); } else { sequenceValue = gen.makeLazyIterable(sequencedArgument, iteratedType, absentType, flags); } JCTree.JCExpression sequenceType = gen.makeJavaType(parameterType, flags); Naming.SyntheticName argName = argName(parameter); JCTree.JCVariableDecl varDecl = gen.makeVar(argName, sequenceType, sequenceValue); gen.at(getPrimary()); bind(parameter, argName, gen.makeJavaType(parameterType, flags), List.of(varDecl)); } private JCExpression makeDefaultedArgumentMethodCall(Parameter param) { JCExpression thisExpr = null; switch (Strategy.defaultParameterMethodOwner(param.getModel())) { case SELF: break; case STATIC: if (param.getDeclaration().isStaticallyImportable()) { thisExpr = gen.makeStaticQualifier(param.getDeclaration()); } break; case OUTER: if(getQmePrimary() != null && !Decl.isConstructor(getPrimaryDeclaration())) thisExpr = callVarName.makeIdent(); break; case OUTER_COMPANION: if (getQmePrimary() != null && !Decl.isConstructor(getPrimaryDeclaration())) { thisExpr = callVarName.makeIdent(); } break; case INIT_COMPANION: thisExpr = varBaseName.suffixedBy(Suffix.$argthis$).makeIdent(); if (isOnValueType()) { thisExpr = gen.boxType(thisExpr, getQmePrimary().getTypeModel()); } break; } JCExpression defaultValueMethodName = gen.naming.makeDefaultedParamMethod(thisExpr, param); JCExpression argExpr = gen.at(getNode()).Apply(null, defaultValueMethodName, makeVarRefArgumentList(param)); return argExpr; } // Make a list of ($arg0, $arg1, ... , $argN) // or ($arg$this$, $arg0, $arg1, ... , $argN) private List makeVarRefArgumentList(Parameter param) { ListBuffer names = new ListBuffer(); if (!Strategy.defaultParameterMethodStatic(getPrimaryDeclaration()) && Strategy.defaultParameterMethodTakesThis(param.getModel())) { names.append(varBaseName.suffixedBy(Suffix.$argthis$).makeIdent()); } // put all the required reified type args too Reference ref = gen.resolveAliasesForReifiedTypeArguments(producedReference); int tpCount = gen.getTypeParameters(ref).size(); for(int tpIndex = 0;tpIndexnCopies(parameterList(param).size(), null)); //} final Naming.SyntheticName argName = varBaseName.suffixedBy(paramIndex); if (this.argsNamesByIndex.containsValue(argName)) { throw new BugException(); } //if (!this.argNames.add(argName)) { // throw new BugException(); //} return argName; } /** Generates the argument name; namedArg may be null if no * argument was given explicitly */ private Naming.SyntheticName reifiedTypeArgName(int index) { return varBaseName.suffixedBy(Suffix.$reified$, index); } private java.util.List parameterList(Parameter param) { Functional functional = (Functional)param.getDeclaration(); return functional.getFirstParameterList().getParameters(); } private int parameterIndex(Parameter param) { return parameterList(param).indexOf(param); } private Type parameterType(Parameter declaredParam, Type pt, int flags) { if(declaredParam == null) return pt; return gen.getTypeForParameter(declaredParam, producedReference, flags); } private void appendVarsForNamedArguments( java.util.List namedArguments, java.util.List declaredParams) { // Assign vars for each named argument given for (Tree.NamedArgument namedArg : namedArguments) { gen.at(namedArg); Parameter declaredParam = namedArg.getParameter(); Naming.SyntheticName argName = argName(declaredParam); if (namedArg instanceof Tree.SpecifiedArgument) { bindSpecifiedArgument((Tree.SpecifiedArgument)namedArg, declaredParam, argName); } else if (namedArg instanceof Tree.MethodArgument) { bindMethodArgument((Tree.MethodArgument)namedArg, declaredParam, argName); } else if (namedArg instanceof Tree.ObjectArgument) { bindObjectArgument((Tree.ObjectArgument)namedArg, declaredParam, argName); } else if (namedArg instanceof Tree.AttributeArgument) { bindAttributeArgument((Tree.AttributeArgument)namedArg, declaredParam, argName); } else { throw BugException.unhandledNodeCase(namedArg); } } } private void bindSpecifiedArgument(Tree.SpecifiedArgument specifiedArg, Parameter declaredParam, Naming.SyntheticName argName) { ListBuffer statements; Tree.Expression expr = specifiedArg.getSpecifierExpression().getExpression(); Type type = parameterType(declaredParam, expr.getTypeModel(), gen.TP_TO_BOUND); final BoxingStrategy boxType = getNamedParameterBoxingStrategy(declaredParam); int jtFlags = 0; int exprFlags = 0; if(boxType == BoxingStrategy.BOXED) jtFlags |= JT_TYPE_ARGUMENT; if(!isParameterRaw(declaredParam)) { exprFlags |= ExpressionTransformer.EXPR_EXPECTED_TYPE_NOT_RAW; } if(isParameterWithConstrainedTypeParameters(declaredParam)) { exprFlags |= ExpressionTransformer.EXPR_EXPECTED_TYPE_HAS_CONSTRAINED_TYPE_PARAMETERS; // we can't just generate types like Foo if the target type param is not raw because the bounds will // not match, so we go raw jtFlags |= JT_RAW; } if(isParameterWithDependentCovariantTypeParameters(declaredParam)) { exprFlags |= ExpressionTransformer.EXPR_EXPECTED_TYPE_HAS_DEPENDENT_COVARIANT_TYPE_PARAMETERS; } if (erasedArgument(TreeUtil.unwrapExpressionUntilTerm(expr))) { exprFlags |= ExpressionTransformer.EXPR_DOWN_CAST; } if (CodegenUtil.downcastForSmall(expr, specifiedArg.getParameter().getModel())) { exprFlags |= ExpressionTransformer.EXPR_UNSAFE_PRIMITIVE_TYPECAST_OK; } JCExpression typeExpr = gen.makeJavaType(type, jtFlags); gen.at(specifiedArg); JCExpression argExpr = gen.expressionGen().transformExpression(expr, boxType, type, exprFlags); gen.at(specifiedArg); JCVariableDecl varDecl = gen.makeVar(argName, typeExpr, argExpr); statements = ListBuffer.of(varDecl); bind(declaredParam, argName, gen.makeJavaType(type, jtFlags), statements.toList()); } private void bindMethodArgument(Tree.MethodArgument methodArg, Parameter declaredParam, Naming.SyntheticName argName) { ListBuffer statements; Function model = methodArg.getDeclarationModel(); List body; boolean prevNoExpressionlessReturn = gen.statementGen().noExpressionlessReturn; boolean prevSyntheticClassBody = gen.expressionGen().withinSyntheticClassBody(Decl.isMpl(model) || gen.expressionGen().isWithinSyntheticClassBody()); try { gen.expressionGen().withinSyntheticClassBody(true); gen.statementGen().noExpressionlessReturn = gen.isAnything(model.getType()); if (methodArg.getBlock() != null) { body = gen.statementGen().transformBlock(methodArg.getBlock()); if (!methodArg.getBlock().getDefinitelyReturns()) { if (gen.isAnything(model.getType())) { body = body.append(gen.make().Return(gen.makeNull())); } else { body = body.append(gen.make().Return(gen.makeErroneous(methodArg.getBlock(), "compiler bug: non-void method does not definitely return"))); } } } else { Expression expr = methodArg.getSpecifierExpression().getExpression(); BoxingStrategy boxing = CodegenUtil.getBoxingStrategy(model); Type type = model.getType(); JCExpression transExpr = gen.expressionGen().transformExpression(expr, boxing, type); JCReturn returnStat = gen.make().Return(transExpr); body = List.of(returnStat); } } finally { gen.expressionGen().withinSyntheticClassBody(prevSyntheticClassBody); gen.statementGen().noExpressionlessReturn = prevNoExpressionlessReturn; } Type callableType = model.appliedReference(null, Collections.emptyList()).getFullType(); CallableBuilder callableBuilder = CallableBuilder.methodArgument(gen.gen(), methodArg, model, callableType, Collections.singletonList(methodArg.getParameterLists().get(0)), gen.classGen().transformMplBody(methodArg.getParameterLists(), model, body)); JCExpression callable = callableBuilder.build(); gen.at(methodArg); JCExpression typeExpr = gen.makeJavaType(callableType, JT_RAW); JCVariableDecl varDecl = gen.makeVar(argName, typeExpr, callable); statements = ListBuffer.of(varDecl); bind(declaredParam, argName, gen.makeJavaType(callableType), statements.toList()); } private void bindObjectArgument(Tree.ObjectArgument objectArg, Parameter declaredParam, Naming.SyntheticName argName) { ListBuffer statements; List object = gen.classGen().transformObjectArgument(objectArg); // No need to worry about boxing (it cannot be a boxed type) JCVariableDecl varDecl = gen.makeLocalIdentityInstance(argName.getName(), Naming.quoteClassName(objectArg.getIdentifier().getText()), false); statements = toStmts(objectArg, object).append(varDecl); bind(declaredParam, argName, gen.makeJavaType(objectArg.getType().getTypeModel()), statements.toList()); } private void bindAttributeArgument(Tree.AttributeArgument attrArg, Parameter declaredParam, Naming.SyntheticName argName) { ListBuffer statements; final Value model = attrArg.getDeclarationModel(); final String name = model.getName(); String className = Naming.getAttrClassName(model, 0); final List attrClass = gen.gen().transformAttribute(model, name, className, null, attrArg.getBlock(), attrArg.getSpecifierExpression(), null, null); TypedReference typedRef = gen.getTypedReference(model); TypedReference nonWideningTypedRef = gen.nonWideningTypeDecl(typedRef); Type nonWideningType = gen.nonWideningType(typedRef, nonWideningTypedRef); Type type = parameterType(declaredParam, model.getType(), 0); final BoxingStrategy boxType = getNamedParameterBoxingStrategy(declaredParam); JCExpression initValue = gen.make().Apply(null, gen.makeSelect(gen.makeUnquotedIdent(className), Naming.getGetterName(model)), List.nil()); initValue = gen.expressionGen().applyErasureAndBoxing( initValue, nonWideningType, !CodegenUtil.isUnBoxed(nonWideningTypedRef.getDeclaration()), boxType, type); JCTree.JCVariableDecl var = gen.make().VarDef( gen.make().Modifiers(FINAL, List.nil()), argName.asName(), gen.makeJavaType(type, boxType==BoxingStrategy.BOXED ? JT_NO_PRIMITIVES : 0), initValue); statements = toStmts(attrArg, attrClass).append(var); bind(declaredParam, argName, gen.makeJavaType(type, boxType==BoxingStrategy.BOXED ? JT_NO_PRIMITIVES : 0), statements.toList()); } private void bind(Parameter param, Naming.SyntheticName argName, JCExpression argType, List statements) { this.vars.appendList(statements); this.argsAndTypes.put(parameterIndex(param), new ExpressionAndType(argName.makeIdent(), argType)); this.argsNamesByIndex.put(parameterIndex(param), argName); this.bound.add(param); } private ListBuffer toStmts(Tree.NamedArgument namedArg, final List listOfStatements) { final ListBuffer result = new ListBuffer(); for (JCTree tree : listOfStatements) { if (tree instanceof JCStatement) { result.append((JCStatement)tree); } else { result.append(gen.make().Exec(gen.makeErroneous(namedArg, "compiler bug: attempt to put a non-statement in a let"))); } } return result; } private final void appendDefaulted(Parameter param, JCExpression argExpr) { // we can't just generate types like Foo if the target type param is not raw because the bounds will // not match, so we go raw int flags = JT_RAW; if (getNamedParameterBoxingStrategy(param) == BoxingStrategy.BOXED) { flags |= JT_TYPE_ARGUMENT; } Type type = gen.getTypeForParameter(param, producedReference, gen.TP_TO_BOUND); Naming.SyntheticName argName = argName(param); JCExpression typeExpr = gen.makeJavaType(type, flags); JCVariableDecl varDecl = gen.makeVar(argName, typeExpr, argExpr); bind(param, argName, gen.makeJavaType(type, flags), List.of(varDecl)); } private BoxingStrategy getNamedParameterBoxingStrategy(Parameter param) { if (param != null) { if (isOnValueType() && Decl.isValueTypeDecl(getParameterTypeForValueType(producedReference, param))) { return BoxingStrategy.UNBOXED; } return CodegenUtil.getBoxingStrategy(param.getModel()); } else { return BoxingStrategy.UNBOXED; } } private boolean appendVarsForDefaulted(java.util.List declaredParams) { boolean hasDefaulted = false; if (!Decl.isOverloaded(getPrimaryDeclaration())) { // append any arguments for defaulted parameters for (Parameter param : declaredParams) { if (bound.contains(param)) { continue; } final JCExpression argExpr; if (Strategy.hasDefaultParameterValueMethod(param)) { // special handling for "element" optional param of java array constructors if(getPrimaryDeclaration() instanceof Class && gen.isJavaArray(((Class)getPrimaryDeclaration()).getType())){ // default values are hard-coded to Java default values, and are actually ignored continue; }else if(getQmePrimary() != null && gen.isJavaArray(getQmePrimary().getTypeModel())){ // we support array methods with optional parameters if(getPrimaryDeclaration() instanceof Function && getPrimaryDeclaration().getName().equals("copyTo")){ if(param.getName().equals("sourcePosition") || param.getName().equals("destinationPosition")){ argExpr = gen.makeInteger(0); hasDefaulted |= true; }else if(param.getName().equals("length")){ argExpr = gen.makeSelect(varBaseName.suffixedBy(Suffix.$argthis$).makeIdent(), "length"); hasDefaulted |= true; }else{ argExpr = gen.makeErroneous(this.getNode(), "compiler bug: argument to copyTo method of java array type not supported: "+param.getName()); } }else{ argExpr = gen.makeErroneous(this.getNode(), "compiler bug: virtual method of java array type not supported: "+getPrimaryDeclaration()); } }else{ argExpr = makeDefaultedArgumentMethodCall(param); hasDefaulted |= true; } } else if (Strategy.hasEmptyDefaultArgument(param)) { argExpr = gen.makeEmptyAsSequential(true); } else if(gen.typeFact().isIterableType(param.getType())){ // must be an iterable we need to fill with empty // FIXME: deal with this erasure bug later argExpr = gen.make().TypeCast(gen.makeJavaType(gen.typeFact().getIterableDeclaration().getType(), AbstractTransformer.JT_RAW), gen.makeEmpty()); } else { // more expensive but worth a try Type appliedType = gen.getTypeForParameter(param, producedReference, AbstractTransformer.TP_TO_BOUND); if(gen.typeFact().isIterableType(appliedType)){ argExpr = gen.make().TypeCast(gen.makeJavaType(gen.typeFact().getIterableDeclaration().getType(), AbstractTransformer.JT_RAW), gen.makeEmpty()); }else{ argExpr = gen.makeErroneous(this.getNode(), "compiler bug: missing argument, and parameter is not defaulted"); } } appendDefaulted(param, argExpr); } } return hasDefaulted; } private final JCVariableDecl makeThis() { // first append $this JCExpression defaultedParameterInstance; // TODO Fix how we figure out the thisType, because it's doesn't // handle type parameters correctly // we used to use thisType = gen.getThisType(getPrimaryDeclaration()); final JCExpression thisType; Reference target = ((Tree.MemberOrTypeExpression)getPrimary()).getTarget(); if (getPrimary() instanceof Tree.BaseMemberExpression && !gen.expressionGen().isWithinSyntheticClassBody()) { if (Decl.withinClassOrInterface(getPrimaryDeclaration())) { // a member method thisType = gen.makeJavaType(target.getQualifyingType(), JT_NO_PRIMITIVES | (getPrimaryDeclaration().isInterfaceMember() && !getPrimaryDeclaration().isShared() ? JT_COMPANION : 0)); TypeDeclaration outer = Decl.getOuterScopeOfMemberInvocation((StaticMemberOrTypeExpression) getPrimary(), getPrimaryDeclaration()); if (outer instanceof Interface && getPrimaryDeclaration().isShared()) { defaultedParameterInstance = gen.naming.makeQuotedThis(); } else { defaultedParameterInstance = gen.naming.makeQualifiedThis(gen.makeJavaType(((TypeDeclaration)outer).getType(), JT_NO_PRIMITIVES | (getPrimaryDeclaration().isInterfaceMember() && !getPrimaryDeclaration().isShared() ? JT_COMPANION : 0))); } } else { // a local or toplevel function thisType = gen.naming.makeName((TypedDeclaration)getPrimaryDeclaration(), Naming.NA_WRAPPER); defaultedParameterInstance = gen.naming.makeName((TypedDeclaration)getPrimaryDeclaration(), Naming.NA_MEMBER); } } else if (getPrimary() instanceof Tree.BaseTypeExpression || getPrimary() instanceof Tree.QualifiedTypeExpression) { TypeDeclaration declaration = (TypeDeclaration)((Tree.MemberOrTypeExpression) getPrimary()).getDeclaration(); thisType = gen.makeJavaType(declaration.getType(), JT_COMPANION); defaultedParameterInstance = gen.make().NewClass( null, null, gen.makeJavaType(declaration.getType(), JT_COMPANION), List.nil(), null); } else { if (isOnValueType()) { thisType = gen.makeJavaType(target.getQualifyingType()); } else { thisType = gen.makeJavaType(target.getQualifyingType(), JT_NO_PRIMITIVES); } defaultedParameterInstance = callVarName.makeIdent(); } JCVariableDecl thisDecl = gen.makeVar(varBaseName.suffixedBy(Suffix.$argthis$), thisType, defaultedParameterInstance); return thisDecl; } @Override protected TransformedInvocationPrimary transformPrimary(JCExpression primaryExpr, String selector) { // We need to build the vars before transforming the primary, because the primary is just a var buildVars(); JCExpression result; TransformedInvocationPrimary actualPrimExpr = super.transformPrimary(primaryExpr, selector); result = actualPrimExpr.expr; if (vars != null && !vars.isEmpty() && primaryExpr != null && selector != null && !getPrimaryDeclaration().isStatic()) { // Prepare the first argument holding the primary for the call Type type = ((Tree.MemberOrTypeExpression)getPrimary()).getTarget().getQualifyingType(); JCExpression varType; if (isOnValueType()) { varType = gen.makeJavaType(getQmePrimary().getTypeModel()); } else { int jtFlags = JT_NO_PRIMITIVES; if (getPrimary() instanceof QualifiedTypeExpression && !getPrimaryDeclaration().isShared() && type.getDeclaration() instanceof Interface) { jtFlags |= JT_COMPANION; } else if ( getPrimary() instanceof Tree.StaticMemberOrTypeExpression && Decl.isPrivateAccessRequiringCompanion((Tree.StaticMemberOrTypeExpression)getPrimary())) { jtFlags |= JT_COMPANION; } if (ExpressionTransformer.isSuperOrSuperOf(this.getQmePrimary()) && (!(this.getPrimary() instanceof Tree.QualifiedMemberExpression) || ((Tree.QualifiedMemberExpression)this.getPrimary()).getMemberOperator() instanceof Tree.MemberOp)) { jtFlags |= JT_COMPANION; } varType = gen.makeJavaType(type, jtFlags); } vars.prepend(gen.makeVar(callVarName, varType, result)); result = callVarName.makeIdent(); } final Constructor ctor = getConstructor(); if (ctor != null && !Decl.isDefaultConstructor(ctor) && !Decl.isJavaArrayWith(ctor)) { argsAndTypes.put(-1, new ExpressionAndType(gen.naming.makeNamedConstructorName(ctor, false), gen.naming.makeNamedConstructorType(ctor, false))); } return new TransformedInvocationPrimary(result, actualPrimExpr.selector); } @Override public void location(CallBuilder callBuilder) { callBuilder.location(namedArgumentList); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy