private void createResultBind(
      final Pattern pattern,
      int index,
      InternalReadAccessor arrayReader,
      AccumulateFunctionCallDescr fc,
      AccumulateFunction function) {
    // bind function result on the result pattern
    Declaration declr = pattern.addDeclaration(fc.getBind());

    Class<?> type = function.getResultType();

    // this bit is different, notice its the ArrayElementReader that we wire up to, not the
    // declaration.
    ArrayElementReader reader = new ArrayElementReader(arrayReader, index, type);
    declr.setReadAccessor(reader);
  }
  private Accumulator[] buildExternalFunctions(
      final RuleBuildContext context,
      final AccumulateDescr accumDescr,
      MVELDialect dialect,
      Map<String, Declaration> decls,
      Map<String, Declaration> sourceOuterDeclr,
      BoundIdentifiers boundIds,
      boolean readLocalsFromTuple) {
    Accumulator[] accumulators;
    List<AccumulateFunctionCallDescr> functions = accumDescr.getFunctions();

    accumulators = new Accumulator[functions.size()];
    // creating the custom array reader
    InternalReadAccessor arrayReader = new SelfReferenceClassFieldReader(Object[].class, "this");

    int index = 0;
    Pattern pattern = (Pattern) context.getBuildStack().peek();
    for (AccumulateFunctionCallDescr func : functions) {
      // build an external function executor
      AccumulateFunction function =
          context.getConfiguration().getAccumulateFunction(func.getFunction());
      if (function == null) {
        context.addError(
            new DescrBuildError(
                accumDescr,
                context.getRuleDescr(),
                null,
                "Unknown accumulate function: '"
                    + func.getFunction()
                    + "' on rule '"
                    + context.getRuleDescr().getName()
                    + "'. All accumulate functions must be registered before building a resource."));
        return null;
      }

      // if there is a binding, create the binding
      if (func.getBind() != null) {
        if (pattern.getDeclaration(func.getBind()) != null) {
          context.addError(
              new DescrBuildError(
                  context.getParentDescr(),
                  accumDescr,
                  null,
                  "Duplicate declaration for variable '"
                      + func.getBind()
                      + "' in the rule '"
                      + context.getRule().getName()
                      + "'"));
        } else {
          createResultBind(pattern, index, arrayReader, func, function);
        }
      }

      final AnalysisResult analysis =
          dialect.analyzeExpression(
              context,
              accumDescr,
              func.getParams().length > 0 ? func.getParams()[0] : "\"\"",
              boundIds);

      MVELCompilationUnit unit =
          dialect.getMVELCompilationUnit(
              func.getParams().length > 0 ? func.getParams()[0] : "\"\"",
              analysis,
              getUsedDeclarations(decls, analysis),
              getUsedDeclarations(sourceOuterDeclr, analysis),
              null,
              context,
              "drools",
              KnowledgeHelper.class,
              readLocalsFromTuple);

      accumulators[index++] = new MVELAccumulatorFunctionExecutor(unit, function);
    }
    return accumulators;
  }