docs: def _DoSubstitute(args, context, callback, trace):
      """Variable substitution, i.e. {foo}
  
    We also implement template formatters here, i.e.  {foo|template bar} as well
    as {.template FOO} for templates that operate on the root of the data dict
    rather than a subtree.
    """
      name, formatters = args
      
      if name is None:
          value = context.Root()  # don't use the cursor
      else:
          try:
              value = context.Lookup(name)
          except TypeError as e:
              raise EvaluationError(
                  'Error evaluating %r in context %r: %r' % (name, context, e))
      
      last_index = len(formatters) - 1
      for i, (f, args, formatter_type) in enumerate(formatters):
          try:
              if formatter_type == TEMPLATE_FORMATTER:
                  template = f.Resolve(context)
                  if i == last_index:
                      # In order to keep less template output in memory, we can just let the
                      # other template write to our callback directly, and then stop.
                      template.execute(value, callback, trace=trace)
                      return  # EARLY RETURN
                  else:
                      # We have more formatters to apply, so explicitly construct 'value'
                      tokens = []
                      template.execute(value, tokens.append, trace=trace)
                      value = JoinTokens(tokens)
              
              elif formatter_type == ENHANCED_FUNC:
                  value = f(value, context, args)
              
              elif formatter_type == SIMPLE_FUNC:
                  value = f(value)
              
              else:
                  assert False, 'Invalid formatter type %r' % formatter_type
          
          except (KeyboardInterrupt, EvaluationError):
              # Don't "wrap" recursive EvaluationErrors
              raise
          
          except Exception as e:
              if formatter_type == TEMPLATE_FORMATTER:
                  raise  # in this case we want to see the original exception
              raise EvaluationError(
                  'Formatting name %r, value %r with formatter %s raised exception: %r '
                  '-- see e.original_exc_info' % (name, value, f, e),
                  original_exc_info=sys.exc_info())
      
      # TODO: Require a string/unicode instance here?
      if value is None:
          raise EvaluationError('Evaluating %r gave None value' % name)
      callback(value)