whole_func_string: function FindCorrespondingFunctions(old_code_tree, new_code_tree) {
  
      // A recursive function that tries to find a correspondence for all
      // child functions and for their inner functions.
      function ProcessNode(old_node, new_node) {
        var scope_change_description =
            IsFunctionContextLocalsChanged(old_node.info, new_node.info);
        if (scope_change_description) {
          old_node.status = FunctionStatus.CHANGED;
        }
  
        var old_children = old_node.children;
        var new_children = new_node.children;
  
        var unmatched_new_nodes_list = [];
        var textually_unmatched_new_nodes_list = [];
  
        var old_index = 0;
        var new_index = 0;
        while (old_index < old_children.length) {
          if (old_children[old_index].status == FunctionStatus.DAMAGED) {
            old_index++;
          } else if (new_index < new_children.length) {
            if (new_children[new_index].info.start_position <
                old_children[old_index].new_start_pos) {
              unmatched_new_nodes_list.push(new_children[new_index]);
              textually_unmatched_new_nodes_list.push(new_children[new_index]);
              new_index++;
            } else if (new_children[new_index].info.start_position ==
                old_children[old_index].new_start_pos) {
              if (new_children[new_index].info.end_position ==
                  old_children[old_index].new_end_pos) {
                old_children[old_index].corresponding_node =
                    new_children[new_index];
                old_children[old_index].textual_corresponding_node =
                    new_children[new_index];
                if (scope_change_description) {
                  old_children[old_index].status = FunctionStatus.DAMAGED;
                  old_children[old_index].status_explanation =
                      "Enclosing function is now incompatible. " +
                      scope_change_description;
                  old_children[old_index].corresponding_node = UNDEFINED;
                } else if (old_children[old_index].status !=
                    FunctionStatus.UNCHANGED) {
                  ProcessNode(old_children[old_index],
                      new_children[new_index]);
                  if (old_children[old_index].status == FunctionStatus.DAMAGED) {
                    unmatched_new_nodes_list.push(
                        old_children[old_index].corresponding_node);
                    old_children[old_index].corresponding_node = UNDEFINED;
                    old_node.status = FunctionStatus.CHANGED;
                  }
                }
              } else {
                old_children[old_index].status = FunctionStatus.DAMAGED;
                old_children[old_index].status_explanation =
                    "No corresponding function in new script found";
                old_node.status = FunctionStatus.CHANGED;
                unmatched_new_nodes_list.push(new_children[new_index]);
                textually_unmatched_new_nodes_list.push(new_children[new_index]);
              }
              new_index++;
              old_index++;
            } else {
              old_children[old_index].status = FunctionStatus.DAMAGED;
              old_children[old_index].status_explanation =
                  "No corresponding function in new script found";
              old_node.status = FunctionStatus.CHANGED;
              old_index++;
            }
          } else {
            old_children[old_index].status = FunctionStatus.DAMAGED;
            old_children[old_index].status_explanation =
                "No corresponding function in new script found";
            old_node.status = FunctionStatus.CHANGED;
            old_index++;
          }
        }
  
        while (new_index < new_children.length) {
          unmatched_new_nodes_list.push(new_children[new_index]);
          textually_unmatched_new_nodes_list.push(new_children[new_index]);
          new_index++;
        }
  
        if (old_node.status == FunctionStatus.CHANGED) {
          if (old_node.info.param_num != new_node.info.param_num) {
            old_node.status = FunctionStatus.DAMAGED;
            old_node.status_explanation = "Changed parameter number: " +
                old_node.info.param_num + " and " + new_node.info.param_num;
          }
        }
        old_node.unmatched_new_nodes = unmatched_new_nodes_list;
        old_node.textually_unmatched_new_nodes =
            textually_unmatched_new_nodes_list;
      }
  
      ProcessNode(old_code_tree, new_code_tree);
  
      old_code_tree.corresponding_node = new_code_tree;
      old_code_tree.textual_corresponding_node = new_code_tree;
  
      Assert(old_code_tree.status != FunctionStatus.DAMAGED,
          "Script became damaged");
    }
func_code_string: function FindCorrespondingFunctions(old_code_tree, new_code_tree) {
  
      // A recursive function that tries to find a correspondence for all
      // child functions and for their inner functions.
      function ProcessNode(old_node, new_node) {
        var scope_change_description =
            IsFunctionContextLocalsChanged(old_node.info, new_node.info);
        if (scope_change_description) {
          old_node.status = FunctionStatus.CHANGED;
        }
  
        var old_children = old_node.children;
        var new_children = new_node.children;
  
        var unmatched_new_nodes_list = [];
        var textually_unmatched_new_nodes_list = [];
  
        var old_index = 0;
        var new_index = 0;
        while (old_index < old_children.length) {
          if (old_children[old_index].status == FunctionStatus.DAMAGED) {
            old_index++;
          } else if (new_index < new_children.length) {
            if (new_children[new_index].info.start_position <
                old_children[old_index].new_start_pos) {
              unmatched_new_nodes_list.push(new_children[new_index]);
              textually_unmatched_new_nodes_list.push(new_children[new_index]);
              new_index++;
            } else if (new_children[new_index].info.start_position ==
                old_children[old_index].new_start_pos) {
              if (new_children[new_index].info.end_position ==
                  old_children[old_index].new_end_pos) {
                old_children[old_index].corresponding_node =
                    new_children[new_index];
                old_children[old_index].textual_corresponding_node =
                    new_children[new_index];
                if (scope_change_description) {
                  old_children[old_index].status = FunctionStatus.DAMAGED;
                  old_children[old_index].status_explanation =
                      "Enclosing function is now incompatible. " +
                      scope_change_description;
                  old_children[old_index].corresponding_node = UNDEFINED;
                } else if (old_children[old_index].status !=
                    FunctionStatus.UNCHANGED) {
                  ProcessNode(old_children[old_index],
                      new_children[new_index]);
                  if (old_children[old_index].status == FunctionStatus.DAMAGED) {
                    unmatched_new_nodes_list.push(
                        old_children[old_index].corresponding_node);
                    old_children[old_index].corresponding_node = UNDEFINED;
                    old_node.status = FunctionStatus.CHANGED;
                  }
                }
              } else {
                old_children[old_index].status = FunctionStatus.DAMAGED;
                old_children[old_index].status_explanation =
                    "No corresponding function in new script found";
                old_node.status = FunctionStatus.CHANGED;
                unmatched_new_nodes_list.push(new_children[new_index]);
                textually_unmatched_new_nodes_list.push(new_children[new_index]);
              }
              new_index++;
              old_index++;
            } else {
              old_children[old_index].status = FunctionStatus.DAMAGED;
              old_children[old_index].status_explanation =
                  "No corresponding function in new script found";
              old_node.status = FunctionStatus.CHANGED;
              old_index++;
            }
          } else {
            old_children[old_index].status = FunctionStatus.DAMAGED;
            old_children[old_index].status_explanation =
                "No corresponding function in new script found";
            old_node.status = FunctionStatus.CHANGED;
            old_index++;
          }
        }
  
        while (new_index < new_children.length) {
          unmatched_new_nodes_list.push(new_children[new_index]);
          textually_unmatched_new_nodes_list.push(new_children[new_index]);
          new_index++;
        }
  
        if (old_node.status == FunctionStatus.CHANGED) {
          if (old_node.info.param_num != new_node.info.param_num) {
            old_node.status = FunctionStatus.DAMAGED;
            old_node.status_explanation = "Changed parameter number: " +
                old_node.info.param_num + " and " + new_node.info.param_num;
          }
        }
        old_node.unmatched_new_nodes = unmatched_new_nodes_list;
        old_node.textually_unmatched_new_nodes =
            textually_unmatched_new_nodes_list;
      }
  
      ProcessNode(old_code_tree, new_code_tree);
  
      old_code_tree.corresponding_node = new_code_tree;
      old_code_tree.textual_corresponding_node = new_code_tree;
  
      Assert(old_code_tree.status != FunctionStatus.DAMAGED,
          "Script became damaged");
    }
func_documentation_string: For each old function (if it is not damaged) tries to find a corresponding function in new script. Typically it should succeed (non-damaged functions by definition may only have changes inside their bodies). However there are reasons for correspondence not to be found; function with unmodified text in new script may become enclosed into other function; the innocent change inside function body may in fact be something like "} function B() {" that splits a function into 2 functions.