public JCNewClass build() { // Generate a subclass of Callable ListBuffer<JCTree> classBody = new ListBuffer<JCTree>(); int numParams = paramLists.getParameters().size(); int minimumParams = 0; for (Parameter p : paramLists.getParameters()) { if (p.isDefaulted() || p.isSequenced()) break; minimumParams++; } boolean isVariadic = minimumParams != numParams; if (parameterListTree != null) { // generate a method for each defaulted param for (Tree.Parameter p : parameterListTree.getParameters()) { if (p.getDefaultArgument() != null || p.getDeclarationModel().isSequenced()) { MethodDefinitionBuilder methodBuilder = gen.classGen().makeParamDefaultValueMethod(false, null, parameterListTree, p); classBody.append(methodBuilder.build()); } } } // collect each parameter type from the callable type model rather than the declarations to get // them all bound java.util.List<ProducedType> parameterTypes = new ArrayList<ProducedType>(numParams); if (forwardCallTo != null) { for (int i = 0; i < numParams; i++) parameterTypes.add(gen.getParameterTypeOfCallable(typeModel, i)); } else { // get them from our declaration for (Parameter p : paramLists.getParameters()) parameterTypes.add(p.getType()); } // now generate a method for each supported minimum number of parameters below 4 // which delegates to the $call$typed method if required for (int i = minimumParams, max = Math.min(numParams, 4); i < max; i++) { classBody.append(makeDefaultedCall(i, isVariadic, parameterTypes)); } // generate the $call method for the max number of parameters, // which delegates to the $call$typed method if required classBody.append(makeDefaultedCall(numParams, isVariadic, parameterTypes)); // generate the $call$typed method if required if (isVariadic && forwardCallTo == null) classBody.append(makeCallTypedMethod(body, parameterTypes)); JCClassDecl classDef = gen.make().AnonymousClassDef(gen.make().Modifiers(0), classBody.toList()); JCNewClass instance = gen.make() .NewClass( null, null, gen.makeJavaType(typeModel, JT_EXTENDS | JT_CLASS_NEW), List.<JCExpression>of(gen.make().Literal(typeModel.getProducedTypeName(true))), classDef); return instance; }
public MethodDefinitionBuilder resultType(Method method, int flags) { if (Decl.isMpl(method)) { // Create a String with the TypeInfo StringBuilder sb = new StringBuilder(); // It's a bunch of nested callables (# of param lists - 1) for (int i = 1; i < method.getParameterLists().size(); i++) { sb.append("ceylon.language::Callable<"); } // Then the return type as defined originally sb.append(method.getType().getProducedTypeQualifiedName()); // And then the parameter types of each nested callable for (int i = method.getParameterLists().size() - 1; i > 0; i--) { ParameterList plist = method.getParameterLists().get(i); for (Parameter p : plist.getParameters()) { sb.append(','); sb.append(p.getType().getProducedTypeQualifiedName()); } sb.append('>'); } return resultType( gen.makeAtType(sb.toString(), false), gen.makeJavaType(gen.functionalReturnType(method), flags)); } else { ProducedTypedReference typedRef = gen.getTypedReference(method); ProducedTypedReference nonWideningTypedRef = gen.nonWideningTypeDecl(typedRef); ProducedType nonWideningType = gen.nonWideningType(typedRef, nonWideningTypedRef); return resultType( makeResultType(nonWideningTypedRef.getDeclaration(), nonWideningType, flags), method); } }
protected final void writeParameters(Declaration decl) throws IOException { if (decl instanceof Functional) { boolean first = true; List<ParameterList> parameterLists = ((Functional) decl).getParameterLists(); for (ParameterList parameterList : parameterLists) { for (Parameter parameter : parameterList.getParameters()) { String doc = getDoc(parameter, linkRenderer()); if (!doc.isEmpty()) { if (first) { first = false; open("div class='parameters section'"); around("span class='title'", "Parameters: "); open("ul"); } open("li"); write(parameter.getName()); write(doc); close("li"); } } } if (!first) { close("ul"); close("div"); } } }
private JCExpression makeDefaultValueCall(Parameter defaultedParam, int i) { // add the default value List<JCExpression> defaultMethodArgs = List.nil(); // pass all the previous values for (int a = i - 1; a >= 0; a--) { Parameter param = paramLists.getParameters().get(a); JCExpression previousValue = gen.makeUnquotedIdent(getCallableTempVarName(param)); defaultMethodArgs = defaultMethodArgs.prepend(previousValue); } // now call the default value method return gen.make() .Apply( null, gen.makeUnquotedIdent(Naming.getDefaultedParamMethodName(null, defaultedParam)), defaultMethodArgs); }
private JCTree makeCallTypedMethod( List<JCStatement> body, java.util.List<ProducedType> parameterTypes) { // make the method MethodDefinitionBuilder methodBuilder = MethodDefinitionBuilder.method(gen, false, Naming.getCallableTypedMethodName()); methodBuilder.modifiers(Flags.PRIVATE); ProducedType returnType = gen.getReturnTypeOfCallable(typeModel); methodBuilder.resultType(gen.makeJavaType(returnType, JT_NO_PRIMITIVES), null); // add all parameters int i = 0; for (Parameter param : paramLists.getParameters()) { ParameterDefinitionBuilder parameterBuilder = ParameterDefinitionBuilder.instance(gen, param.getName()); JCExpression paramType = gen.makeJavaType(parameterTypes.get(i)); parameterBuilder.type(paramType, null); methodBuilder.parameter(parameterBuilder); i++; } // Return the call result, or null if a void method methodBuilder.body(body); return methodBuilder.build(); }
protected final void writeParameterList(Functional f) throws IOException { for (ParameterList lists : f.getParameterLists()) { write("("); boolean first = true; for (Parameter param : lists.getParameters()) { if (!first) { write(", "); } else { first = false; } if (param instanceof FunctionalParameter) { writeFunctionalParameter((FunctionalParameter) param); } else if (param.isSequenced()) { writeSequencedParameter(param); } else { linkRenderer().to(param.getType()).write(); write(" ", param.getName()); } } write(")"); } }
private JCTree makeDefaultedCall( int i, boolean isVariadic, java.util.List<ProducedType> parameterTypes) { // collect every parameter int a = 0; ListBuffer<JCStatement> stmts = new ListBuffer<JCStatement>(); for (Parameter param : paramLists.getParameters()) { // don't read default parameter values for forwarded calls if (forwardCallTo != null && i == a) break; // read the value JCExpression paramExpression = getTypedParameter(param, a, i > 3, parameterTypes); JCExpression varInitialExpression; if (param.isDefaulted() || param.isSequenced()) { if (i > 3) { // must check if it's defined JCExpression test = gen.make() .Binary(JCTree.GT, gen.makeSelect(getParamName(0), "length"), gen.makeInteger(a)); JCExpression elseBranch = makeDefaultValueCall(param, a); varInitialExpression = gen.make().Conditional(test, paramExpression, elseBranch); } else if (a >= i) { // get its default value because we don't have it varInitialExpression = makeDefaultValueCall(param, a); } else { // we must have it varInitialExpression = paramExpression; } } else { varInitialExpression = paramExpression; } // store it in a local var JCStatement var = gen.make() .VarDef( gen.make().Modifiers(Flags.FINAL), gen.naming.makeUnquotedName(getCallableTempVarName(param)), gen.makeJavaType( parameterTypes.get(a), CodegenUtil.isUnBoxed(param) ? 0 : gen.JT_NO_PRIMITIVES), varInitialExpression); stmts.append(var); a++; } if (forwardCallTo != null) { InvocationBuilder invocationBuilder = InvocationBuilder.forCallableInvocation(gen, forwardCallTo, paramLists, i); boolean prevCallableInv = gen.expressionGen().withinCallableInvocation(true); try { stmts.append(gen.make().Return(invocationBuilder.build())); } finally { gen.expressionGen().withinCallableInvocation(prevCallableInv); } } else if (isVariadic) { // chain to n param typed method List<JCExpression> args = List.nil(); // pass along the parameters for (a = paramLists.getParameters().size() - 1; a >= 0; a--) { Parameter param = paramLists.getParameters().get(a); args = args.prepend(gen.makeUnquotedIdent(getCallableTempVarName(param))); } JCMethodInvocation chain = gen.make().Apply(null, gen.makeUnquotedIdent(Naming.getCallableTypedMethodName()), args); stmts.append(gen.make().Return(chain)); } else { // insert the method body directly stmts.appendList(this.body); } List<JCStatement> body = stmts.toList(); return makeCallMethod(body, i); }