Class: Janeway::Interpreters::DescendantSegmentInterpreter

Inherits:
Base
  • Object
show all
Defined in:
lib/janeway/interpreters/descendant_segment_interpreter.rb

Overview

Find all descendants of the current input that match the selector in the DescendantSegment

Constant Summary

Constants inherited from Base

Base::NOTHING

Instance Attribute Summary

Attributes inherited from Base

#next, #node

Instance Method Summary collapse

Methods inherited from Base

#as_json, #initialize, #selector, #to_s, #type

Constructor Details

This class inherits a constructor from Janeway::Interpreters::Base

Instance Method Details

#interpret(input, parent, root, path) ⇒ Array<AST::Expression>

Find all descendants of the current input that match the selector in the DescendantSegment

Parameters:

  • input (Array, Hash)

    the results of processing so far

  • parent (Array, Hash)

    parent of the input object

  • root (Array, Hash)

    the entire input

  • path (Array<String>)

    elements of normalized path to the current input

Returns:



18
19
20
21
22
# File 'lib/janeway/interpreters/descendant_segment_interpreter.rb', line 18

def interpret(input, parent, root, path)
  visit(input, parent, path) do |node, parent_of_node, sub_path|
    @next.interpret(node, parent_of_node, root, sub_path)
  end
end

#visit(input, parent, path) ⇒ Object

Visit all descendants of input and concatenate the results of block at each node. Iterative depth-first pre-order — a recursive implementation would risk SystemStackError on deep JSON and allocated an array-per-node plus a flatten pass.

Parameters:

  • input (Array, Hash)

    the results of processing so far

  • parent (Array, Hash)

    parent of the input object

  • path (Array<String>)

    elements of normalized path to the current input



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/janeway/interpreters/descendant_segment_interpreter.rb', line 32

def visit(input, parent, path)
  results = []
  stack = [[input, parent, path]]
  until stack.empty?
    node, node_parent, node_path = stack.pop
    results.concat(yield(node, node_parent, node_path))

    case node
    when Array
      # Push in reverse so the leftmost child is popped first (pre-order).
      i = node.size - 1
      while i >= 0
        stack.push([node[i], node, node_path + [i]])
        i -= 1
      end
    when Hash
      # Iterate to an array once so we can walk it in reverse.
      pairs = node.to_a
      i = pairs.size - 1
      while i >= 0
        k, v = pairs[i]
        stack.push([v, node, node_path + [k]])
        i -= 1
      end
    end
    # Basic (non-container) types have no descendants — nothing to push.
  end
  results
end