private Expr visitAccumulator( Span span, List<GeneratorClause> gens, Op op, Expr body, List<StaticArg> staticArgs, boolean isParen) { body = visitGenerators(span, gens, body); /** * * If the accumulation is a nested reduction like BIG OP [ys <- gg] BIG OT <| f y | y <- ys |> * , visitGenerators returns a tuple of ((BIG OT, f), gg) (this should be refactored, though) */ Expr res; if (body instanceof FnExpr) { Expr opexp = ExprFactory.makeOpExpr(span, op, staticArgs); res = ExprFactory.make_RewriteFnApp( span, BIGOP_NAME, ExprFactory.makeTupleExpr(span, opexp, body)); } else if (body instanceof TupleExpr) { /** * * For BIG OP [ys <- gg] BIG OT <| f y | y <- ys |> The nested reduction is replaced with * __bigOperator2(BIG OP, BIG OT, gg) * * <p>This is similar to forOpExpr(OpExpr that) . * * <p>by Kento */ // a tuple of the inner Accumulator (op, body) and the gg TupleExpr tuple = (TupleExpr) body; TupleExpr innerAccumTuple = (TupleExpr) tuple.getExprs().get(0); Expr opexpI = (Expr) innerAccumTuple.getExprs().get(0); Expr innerBody = (Expr) innerAccumTuple.getExprs().get(1); Expr opexpO = ExprFactory.makeOpExpr(span, op, staticArgs); Expr gg = tuple.getExprs().get(1); res = ExprFactory.make_RewriteFnApp( span, BIGOP2_NAME, ExprFactory.makeTupleExpr(span, opexpO, opexpI, gg, innerBody)); } else res = bug(body, "Function expressions or tuple expressions are expected."); if (isParen) res = ExprFactory.makeInParentheses(res); return (Expr) recur(res); }
@Override public Node forOpExpr(OpExpr that) { FunctionalRef op_result = (FunctionalRef) recur(that.getOp()); /** * * For BIG OP <| BIG OT <| f y | y <- ys |> | ys <- gg |> Is this case, BIG <||> is being * removed. The nested reduction is replaced with __bigOperator2(BIG OP, BIG OT, gg) * * <p>by Kento */ String str = op_result.toString(); String theListEnclosingOperatorName = "BIG <| BIG |>"; String someBigOperatorName = "BIG"; // make sure the body is of application of some big operator if ((str.length() >= someBigOperatorName.length() && str.substring(0, someBigOperatorName.length()).equals(someBigOperatorName))) { // make sure that BIG OP (Accumulator (BIG <||>, gs)) if (that.getArgs().size() == 1 && that.getArgs().get(0) instanceof Accumulator && ((Accumulator) that.getArgs().get(0)) .getAccOp() .toString() .equals(theListEnclosingOperatorName)) { Accumulator acc = (Accumulator) that.getArgs().get(0); Expr body = visitGenerators(NodeUtil.getSpan(acc), acc.getGens(), acc.getBody()); /** * * If the accumulation is a nested reduction like <| BIG OT <| f y | y <- ys |> | ys <- gg * |> , visitGenerators returns a tuple of ((BIG OT, f), gg) (this should be refactored, * though) In this case, the nested reduction is replaced with __bigOperator2 */ if (body instanceof TupleExpr) { // a tuple of the inner Accumulator (op, body) and the gg TupleExpr tuple = (TupleExpr) body; TupleExpr innerAccumTuple = (TupleExpr) tuple.getExprs().get(0); Expr opexpI = (Expr) innerAccumTuple.getExprs().get(0); Expr innerBody = (Expr) innerAccumTuple.getExprs().get(1); FunctionalRef ref = (FunctionalRef) op_result; IdOrOp name = ref.getNames().get(0); // make sure the operator is actually an operator if (!(name instanceof Op)) return null; Expr opexpO = ExprFactory.makeOpExpr(NodeUtil.getSpan(that), (Op) name, ref.getStaticArgs()); Expr gg = tuple.getExprs().get(1); Expr res = ExprFactory.make_RewriteFnApp( NodeUtil.getSpan(that), BIGOP2_NAME, ExprFactory.makeTupleExpr(NodeUtil.getSpan(body), opexpO, opexpI, gg, innerBody)); return (Expr) recur(res); } } } List<Expr> args_result = recurOnListOfExpr(that.getArgs()); OpExpr new_op; if (op_result == that.getOp() && args_result == that.getArgs()) { new_op = that; } else { new_op = ExprFactory.makeOpExpr( NodeUtil.getSpan(that), NodeUtil.isParenthesized(that), NodeUtil.getExprType(that), op_result, args_result); } return cleanupOpExpr(new_op); }