[Compiler] Differences in building Scan and Reduce expression

Hi,
I have notice in chapel/compiler/AST/build.cpp (latest version), buildScanExpr used new FnSymbol(astr("chpl__scan", istr(uid++))); and buildReduceExpr used a primitive tag.
In release1.18, they both using FnSymbol, I think scan and reduce works very similarly, is there any reason for not using the primitive tag for scan?

You are right, while reduce and scans work similarly, they are implemented very differently. Reduce expressions are implemented largely within the compiler because this implementation also works for reduce intents on forall loops. Scans are implemented mostly in Chapel code because it is easier to write and to maintain than doing the same thing within the compiler.

1 Like

Hi Vass,
Within the compiler means built in c++ code?
Why would be using Chapel code easier?
Can you please elaborate?
Thank you.

Hi Allie,

There’s probably some specific details with scans and reduce expressions that Vass is more qualified to speak to, but in general we try to lean on our implementation of classes and records for certain of the more complex types Chapel provides. If we can use that general functionality to accomplish everything we want to, without having to add specific actions to the compiler to support the type, that makes it more maintainable overall.

It also makes it easier for users to add their own alternatives to the type, or to extend it themselves. And it’s a good way to test records and classes in a more real world scenario.

Thanks,
Lydia

1 Like

To add to Lydia’s response, and answer “why would be using Chapel code easier?”, consider this piece of implementation for scans:

  proc chpl__scanIterator(op, data) {
    use Reflection;
    param supportsPar = isArray(data) && canResolveMethod(data, "_scan", op);
    if (supportsPar) {
      return data._scan(op);
    } else {
      compilerWarning("scan has been serialized (see issue #12482)");
      var arr = for d in data do chpl__accumgen(op, d);

      delete op;
      return arr;
    }
  }

This is pretty readable.

By contrast, if I were building the same function in C++ code using new CallExpr(....), new CondStmt(.....), etc., it would be much larger code size and much less readable and maintainable.

1 Like