module TDiff

def tdiff_recursive(tree,&block)

Other tags:
    Since: - 0.3.2

Other tags:
    Yieldparam: node -
    Yieldparam: change -

Other tags:
    Yield: -

Parameters:
  • tree (#tdiff_each_child) --
def tdiff_recursive(tree,&block)
  c = Hash.new { |hash,key| hash[key] = Hash.new(0) }
  x = enum_for(:tdiff_each_child,self)
  y = enum_for(:tdiff_each_child,tree)
  x.each_with_index do |xi,i|
    y.each_with_index do |yj,j|
      c[i][j] = if xi.tdiff_equal(yj)
                  c[i-1][j-1] + 1
                else
                  if c[i][j-1] > c[i-1][j]
                    c[i][j-1]
                  else
                    c[i-1][j]
                  end
                end
    end
  end
  unchanged = []
  changes = []
  x_backtrack = x.each_with_index.reverse_each
  y_backtrack = y.each_with_index.reverse_each
  next_child = lambda { |children|
    begin
      children.next
    rescue StopIteration
      # end of iteration, return a -1 index
      [nil, -1]
    end
  }
  xi, i = next_child[x_backtrack]
  yj, j = next_child[y_backtrack]
  until (i == -1 && j == -1)
    if (i != -1 && j != -1 && xi.tdiff_equal(yj))
      changes.unshift [' ', xi]
      unchanged.unshift [xi, yj]
      xi, i = next_child[x_backtrack]
      yj, j = next_child[y_backtrack]
    else
      if (j >= 0 && (i == -1 || c[i][j-1] >= c[i-1][j]))
        changes.unshift ['+', yj]
        yj, j = next_child[y_backtrack]
      elsif (i >= 0 && (j == -1 || c[i][j-1] < c[i-1][j]))
        changes.unshift ['-', xi]
        xi, i = next_child[x_backtrack]
      end
    end
  end
  # explicitly discard the c matrix
  c = nil
  # sequentially iterate over the changed nodes
  changes.each(&block)
  changes = nil
  # recurse down through unchanged nodes
  unchanged.each { |a,b| a.tdiff_recursive(b,&block) }
  unchanged = nil
end