Sha256: 9a1cfbd18411455bbf910f10aa8587a4c949a834847cc4c5ddb11ebeb8078862

Contents?: true

Size: 1.54 KB

Versions: 4

Compression:

Stored size: 1.54 KB

Contents

module Hexp
  class MutableTreeWalk
    attr_reader :root, :path, :result

    def initialize(root)
      @root = root
      @path = [root]
      @replacements = [{}]
      @result = nil
    end

    def next!
      return if end?
      if current.children.any?
        @path << current.children.first
        @replacements << {}
      elsif @path.length == 1
        @result = @path.pop
      else
        backtrack_and_right!
      end
    end

    def backtrack_and_right!
      while at_rightmost_child?
        @path.pop
        handle_replacements!
        if @path.length == 1 #back at start, we're done
          @result = @path.pop
          return
        end
      end
      go_right!
    end

    def replace!(val)
      @replacements.last[current_idx] = val
    end

    def handle_replacements!
      replacements = @replacements.pop
      return if replacements.empty?
      new_children = [*current.children]
      replacements.each do |idx, val|
        new_children[idx..idx] = val
      end
      new_node = current.set_children(new_children)
      if @path.length == 1
        @path = [new_node]
      else
        @replacements.last[current_idx] = new_node
      end
    end

    def at_rightmost_child?
      current.equal? parent.children.last
    end

    def go_right!
      @path[-1] = parent.children[current_idx + 1]
    end

    def current_idx
      parent.children.find_index { |ch| current.equal?(ch) }
    end

    def parent
      @path[-2]
    end

    def current
      @path.last
    end

    def end?
      @path.empty?
    end
  end
end

Version data entries

4 entries across 4 versions & 1 rubygems

Version Path
hexp-0.4.6 lib/hexp/mutable_tree_walk.rb
hexp-0.4.5 lib/hexp/mutable_tree_walk.rb
hexp-0.4.4 lib/hexp/mutable_tree_walk.rb
hexp-0.4.3 lib/hexp/mutable_tree_walk.rb