Example #1
0
  @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");
  }
Example #3
0
 @Override
 public Function<Object[], ?> visit(ParameterExpression e) {
   final int index = e.getIndex();
   return t -> t[index];
 }
Example #4
0
  @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);
  }