class_docstr: The base class for code-printing subclasses.
class_docstr_tok: ["The","base","class","for","code-printing","subclasses","."]
code: def _doprint_loops(self, expr, assign_to=None):
      # Here we print an expression that contains Indexed objects, they
      # correspond to arrays in the generated code.  The low-level implementation
      # involves looping over array elements and possibly storing results in temporary
      # variables or accumulate it in the assign_to object.
  
      if self._settings.get("contract", True):
          from sympy.tensor import get_contraction_structure
  
          # Setup loops over non-dummy indices  --  all terms need these
          indices = self._get_expression_indices(expr, assign_to)
          # Setup loops over dummy indices  --  each term needs separate treatment
          dummies = get_contraction_structure(expr)
      else:
          indices = []
          dummies = {None: (expr,)}
      openloop, closeloop = self._get_loop_opening_ending(indices)
  
      # terms with no summations first
      if None in dummies:
          text = StrPrinter.doprint(self, Add(*dummies[None]))
      else:
          # If all terms have summations we must initialize array to Zero
          text = StrPrinter.doprint(self, 0)
  
      # skip redundant assignments (where lhs == rhs)
      lhs_printed = self._print(assign_to)
      lines = []
      if text != lhs_printed:
          lines.extend(openloop)
          if assign_to is not None:
              text = self._get_statement(
                  "%s = %s" % (lhs_printed, text)
              )
          lines.append(text)
          lines.extend(closeloop)
  
      # then terms with summations
      for d in dummies:
          if isinstance(d, tuple):
              indices = self._sort_optimized(d, expr)
              openloop_d, closeloop_d = self._get_loop_opening_ending(
                  indices
              )
  
              for term in dummies[d]:
                  if term in dummies and not (
                      [list(f.keys()) for f in dummies[term]]
                      == [[None] for f in dummies[term]]
                  ):
                      # If one factor in the term has it's own internal
                      # contractions, those must be computed first.
                      # (temporary variables?)
                      raise NotImplementedError(
                          "FIXME: no support for contractions in factor yet"
                      )
                  else:
                      # We need the lhs expression as an accumulator for
                      # the loops, i.e
                      #
                      # for (int d=0; d < dim; d++){
                      #    lhs[] = lhs[] + term[][d]
                      # }           ^.................. the accumulator
                      #
                      # We check if the expression already contains the
                      # lhs, and raise an exception if it does, as that
                      # syntax is currently undefined.  FIXME: What would be
                      # a good interpretation?
                      if assign_to is None:
                          raise AssignmentError(
                              "need assignment variable for loops"
                          )
                      if term.has(assign_to):
                          raise ValueError(
                              "FIXME: lhs present in rhs,\
                                  this is undefined in CodePrinter"
                          )
  
                      lines.extend(openloop)
                      lines.extend(openloop_d)
                      text = "%s = %s" % (
                          lhs_printed,
                          StrPrinter.doprint(self, assign_to + term),
                      )
                      lines.append(self._get_statement(text))
                      lines.extend(closeloop_d)
                      lines.extend(closeloop)
  
      return "\n".join(lines)
  
imports: from __future__ import annotations
  from typing import Any
  from functools import wraps
  from sympy.core import Add, Mul, Pow, S, sympify, Float
  from sympy.core.basic import Basic
  from sympy.core.expr import UnevaluatedExpr
  from sympy.core.function import Lambda
  from sympy.core.mul import _keep_coeff
  from sympy.core.sorting import default_sort_key
  from sympy.core.symbol import Symbol
  from sympy.functions.elementary.complexes import re
  from sympy.printing.str import StrPrinter
  from sympy.printing.precedence import precedence, PRECEDENCE
label_desc: Use image node_id 4 for calling the CodePrinter obj's underlying member method code with example usage: obj._doprint_loops(expr, assign_to) and returns: str