compiler/resolution/lowerIterators.cpp
/// \param call A for loop block primitive.
\param call A for loop block primitive.
\ param call A for loop block primitive .
static bool
expandIteratorInline(ForLoop* forLoop) {
  Symbol*   ic       = forLoop->iteratorGet()->symbol();
  FnSymbol* iterator = getTheIteratorFn(ic);
  if (fReportInlinedIterators) {
    ModuleSymbol *mod = iterator->getModule();
    if (developer || mod->modTag == MOD_USER) {
      printf("Inlined iterator (%s) in module %s (%s:%d)\n", iterator->cname,
              mod->name, iterator->fname(), iterator->linenum());
    }
  }
  if (iterator->hasFlag(FLAG_RECURSIVE_ITERATOR)) {
    if (forLoop->parentSymbol->hasFlag(FLAG_RECURSIVE_ITERATOR)) {
      return false;
     vass: ditto for task functions called from recursive iterators
    } else if (taskFunInRecursiveIteratorSet.set_in(forLoop->parentSymbol)) {
      return false;
    } else if (containsYield(forLoop)) {
       Inlining a recursive iterator into a loop with a 'yield' pushes
       that 'yield' into one of _rec_ functions, where it dangles. Ex.:
       test/library/standard/FileSystem/filerator/bradc/findfiles-par.chpl
      return false;
    } else {
      expandRecursiveIteratorInline(forLoop);
      INT_ASSERT(!forLoop->inTree());
      return true;
    }
  } else {
    SET_LINENO(forLoop);
    Symbol*       index = forLoop->indexGet()->symbol();
    BlockStmt*    ibody = iterator->body->copy();
    std::vector<SymExpr*> symExprs;
    bool isOrderIndependent = forLoop->isOrderIndependent();
    if (preserveInlinedLineNumbers == false) {
      reset_ast_loc(ibody, forLoop);
    }
     and the entire for loop block is replaced by the iterator body.
    forLoop->replace(ibody);
     if the loop being expanded was order independent, all of the yielding
     loops in the body are also order independent. Note that this must occur
     after the ibody replaces the forLoop since findEnclosingLoop() requires
     that its argument be in the AST. It must occur before yields are
     replaced in the functions below though.
    if (isOrderIndependent) {
      std::vector<CallExpr*> callExprs;
      collectCallExprs(ibody, callExprs);
      for_vector(CallExpr, call, callExprs) {
        if (call->isPrimitive(PRIM_YIELD)) {
          if (LoopStmt* loop = LoopStmt::findEnclosingLoop(call)) {
            if (loop->isCoforallLoop() == false) {
              loop->orderIndependentSet(isOrderIndependent);
            }
          }
        }
      }
    }
     Replace yield statements in the inlined iterator body with copies
     of the body of the For Loop that invoked the iterator, substituting
     the yielded index for the iterator formal.
    expandBodyForIteratorInline(forLoop, ibody, index);
    collectSymExprs(ibody, symExprs);
    replaceIteratorFormals(iterator, ic, symExprs);
     We can return true if forLoop has been removed from the tree.
    INT_ASSERT(!forLoop->inTree());
    return true;
  }
}
static bool expandIteratorInline ( ForLoop * forLoop ) { Symbol * ic = forLoop -> iteratorGet ( ) -> symbol ( ) ; FnSymbol * iterator = getTheIteratorFn ( ic ) ; if ( fReportInlinedIterators ) { ModuleSymbol * mod = iterator -> getModule ( ) ; if ( developer || mod -> modTag == MOD_USER ) { printf ( " \n " , iterator -> cname , mod -> name , iterator -> fname ( ) , iterator -> linenum ( ) ) ; } } if ( iterator -> hasFlag ( FLAG_RECURSIVE_ITERATOR ) ) { if ( forLoop -> parentSymbol -> hasFlag ( FLAG_RECURSIVE_ITERATOR ) ) { return false ; } else if ( taskFunInRecursiveIteratorSet . set_in ( forLoop -> parentSymbol ) ) { return false ; } else if ( containsYield ( forLoop ) ) { return false ; } else { expandRecursiveIteratorInline ( forLoop ) ; INT_ASSERT ( ! forLoop -> inTree ( ) ) ; return true ; } } else { SET_LINENO ( forLoop ) ; Symbol * index = forLoop -> indexGet ( ) -> symbol ( ) ; BlockStmt * ibody = iterator -> body -> copy ( ) ; std :: vector < SymExpr * > symExprs ; bool isOrderIndependent = forLoop -> isOrderIndependent ( ) ; if ( preserveInlinedLineNumbers == false ) { reset_ast_loc ( ibody , forLoop ) ; } forLoop -> replace ( ibody ) ; if ( isOrderIndependent ) { std :: vector < CallExpr * > callExprs ; collectCallExprs ( ibody , callExprs ) ; for_vector ( CallExpr , call , callExprs ) { if ( call -> isPrimitive ( PRIM_YIELD ) ) { if ( LoopStmt * loop = LoopStmt :: findEnclosingLoop ( call ) ) { if ( loop -> isCoforallLoop ( ) == false ) { loop -> orderIndependentSet ( isOrderIndependent ) ; } } } } } expandBodyForIteratorInline ( forLoop , ibody , index ) ; collectSymExprs ( ibody , symExprs ) ; replaceIteratorFormals ( iterator , ic , symExprs ) ; INT_ASSERT ( ! forLoop -> inTree ( ) ) ; return true ; } }
\param call A for loop block primitive.
\ param call A for loop block primitive .
// Returns true if the given ForLoop was handled (converted and removed from // the tree); false otherwise. // NOAKES 2014/11/30  Only 6 tests, some with minor variations, use this path // The iterand of the forLoop is marked as a recursive iterator.  This is // the case we are looking for.  But first, we have to weed out a few // troublesome cases. // sjd: // loops over recursive iterators in recursive iterators only need // to be handled in the recursive iterator function // // vass: ditto for task functions called from recursive iterators // Inlining a recursive iterator into a loop with a 'yield' pushes // that 'yield' into one of _rec_ functions, where it dangles. Ex.: // test/library/standard/FileSystem/filerator/bradc/findfiles-par.chpl // and the entire for loop block is replaced by the iterator body. // if the loop being expanded was order independent, all of the yielding // loops in the body are also order independent. Note that this must occur // after the ibody replaces the forLoop since findEnclosingLoop() requires // that its argument be in the AST. It must occur before yields are // replaced in the functions below though. // Replace yield statements in the inlined iterator body with copies // of the body of the For Loop that invoked the iterator, substituting // the yielded index for the iterator formal. // We can return true if forLoop has been removed from the tree.