code: private SoyValue visitNullSafeNodeRecurse(ExprNode node) {
      switch (node.getKind()) {
        case VAR_REF_NODE:
          return visitNullSafeVarRefNode((VarRefNode) node);
  
        case FIELD_ACCESS_NODE:
          return visitNullSafeFieldAccessNode((FieldAccessNode) node);
  
        case ITEM_ACCESS_NODE:
          return visitNullSafeItemAccessNode((ItemAccessNode) node);
  
        default:
          return visit(node);
      }
    }
docs: Helper function which recursively evaluates data references. This bypasses the normal visitor
  mechanism as follows: As soon as the EvalVisitor sees a node which is a data reference, it
  calls this function which evaluates that data reference and any descendant data references,
  returning either the result of the evaluation, or a special sentinel value which indicates that
  a null-safety check failed. Internally this sentinel value is used to short-circuit evaluations
  that would otherwise fail because of the null value.
  
  <p>If any descendant node is not a data reference, then this uses the normal visitor mechanism
  to evaluate that node.
  
  <p>The reason for bypassing the normal visitor mechanism is that we want to detect the
  transition between data-reference nodes and non-data-reference nodes. So for example, if a
  FieldAccessNode has a parent node which is a data reference, we want to propagate the sentinel
  value upward, whereas if the parent is not a data reference, then we want to convert the
  sentinel value into a regular null value.
  
  @param node The node to evaluate.
  @return The result of evaluating the node.