@Override public Function<Object[], ?> visit(LambdaExpression<?> e) { final Function<Object[], ?> f = e.getBody().accept(this); int size = e.getParameters().size(); List<Function<Object[], ?>> ppe = new ArrayList<>(size); for (ParameterExpression p : e.getParameters()) ppe.add(p.accept(this)); Function<Object[], Object[]> params = pp -> { Object[] r = new Object[ppe.size()]; int index = 0; for (Function<Object[], ?> pe : ppe) { r[index++] = pe.apply(pp); } return r; }; return f.compose(params); }
@Override void accept(ExpressionWriter writer, int lprec, int rprec) { // "new Function1() { // public Result apply(T1 p1, ...) { // <body> // } // // bridge method // public Object apply(Object p1, ...) { // return apply((T1) p1, ...); // } // } // // if any arguments are primitive there is an extra bridge method: // // new Function1() { // public double apply(double p1, int p2) { // <body> // } // // box bridge method // public Double apply(Double p1, Integer p2) { // return apply(p1.doubleValue(), p2.intValue()); // } // // bridge method // public Object apply(Object p1, Object p2) { // return apply((Double) p1, (Integer) p2); // } List<String> params = new ArrayList<String>(); List<String> bridgeParams = new ArrayList<String>(); List<String> bridgeArgs = new ArrayList<String>(); List<String> boxBridgeParams = new ArrayList<String>(); List<String> boxBridgeArgs = new ArrayList<String>(); for (ParameterExpression parameterExpression : parameterList) { final Type parameterType = parameterExpression.getType(); final Type parameterBoxType = Types.box(parameterType); final String parameterBoxTypeName = Types.className(parameterBoxType); params.add(parameterExpression.declString()); bridgeParams.add(parameterExpression.declString(Object.class)); bridgeArgs.add("(" + parameterBoxTypeName + ") " + parameterExpression.name); boxBridgeParams.add(parameterExpression.declString(parameterBoxType)); boxBridgeArgs.add( parameterExpression.name + (Primitive.is(parameterType) ? "." + Primitive.of(parameterType).primitiveName + "Value()" : "")); } Type bridgeResultType = Functions.FUNCTION_RESULT_TYPES.get(this.type); if (bridgeResultType == null) { bridgeResultType = body.getType(); } Type resultType2 = bridgeResultType; if (bridgeResultType == Object.class && !params.equals(bridgeParams) && !(body.getType() instanceof TypeVariable)) { resultType2 = body.getType(); } String methodName = getAbstractMethodName(); writer .append("new ") .append(type) .append("()") .begin(" {\n") .append("public ") .append(Types.className(resultType2)) .list(" " + methodName + "(", ", ", ") ", params) .append(Blocks.toFunctionBlock(body)); // Generate an intermediate bridge method if at least one parameter is // primitive. if (!boxBridgeParams.equals(params)) { writer .append("public ") .append(Types.boxClassName(bridgeResultType)) .list(" " + methodName + "(", ", ", ") ", boxBridgeParams) .begin("{\n") .list("return " + methodName + "(\n", ",\n", ");\n", boxBridgeArgs) .end("}\n"); } // Generate a bridge method. Argument types are looser (as if every // type parameter is set to 'Object'). // // Skip the bridge method if there are no arguments. It would have the // same overload as the regular method. if (!bridgeParams.equals(params)) { writer .append("public ") .append(Types.boxClassName(bridgeResultType)) .list(" " + methodName + "(", ", ", ") ", bridgeParams) .begin("{\n") .list("return " + methodName + "(\n", ",\n", ");\n", bridgeArgs) .end("}\n"); } writer.end("}\n"); }
@Override public Function<Object[], ?> visit(ParameterExpression e) { final int index = e.getIndex(); return t -> t[index]; }
@Override public Function<Object[], ?> visit(MemberExpression e) { final Member m = e.getMember(); Expression ei = e.getInstance(); final Function<Object[], ?> instance = ei != null ? ei.accept(this) : null; int size = e.getParameters().size(); List<Function<Object[], ?>> ppe = new ArrayList<>(size); for (ParameterExpression p : e.getParameters()) ppe.add(p.accept(this)); Function<Object[], Object[]> params = pp -> { Object[] r = new Object[ppe.size()]; int index = 0; for (Function<Object[], ?> pe : ppe) { r[index++] = pe.apply(pp); } return r; }; Function<Object[], ?> field = t -> { try { return ((Field) m).get(instance == null ? null : instance.apply(t)); } catch (IllegalArgumentException | IllegalAccessException ex) { throw new RuntimeException(ex); } }; Function<Object[], ?> method = t -> { Object inst; if (instance != null) { inst = instance.apply(t); } else inst = null; try { Object[] pp = params.apply(t); return ((Method) m).invoke(inst, pp); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { throw new RuntimeException(ex); } }; Function<Object[], ?> ctor = t -> { try { return ((Constructor<?>) m).newInstance(params.apply(t)); } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { throw new RuntimeException(ex); } }; Function<Object[], ?> member; if (m instanceof Field) member = field; else if (m instanceof Method) member = method; else member = ctor; return member; // .compose(params); }