Class: Rjq::AST::Foreach

Inherits:
Node
  • Object
show all
Defined in:
lib/rjq/ast.rb

Instance Attribute Summary collapse

Attributes inherited from Node

#source_span

Instance Method Summary collapse

Methods inherited from Node

#assign_value, #invalid_path_message, #paths, #take, #with_source_span

Constructor Details

#initialize(generator, variable, initial, update, extract) ⇒ Foreach

Returns a new instance of Foreach.



728
729
730
731
732
733
734
# File 'lib/rjq/ast.rb', line 728

def initialize(generator, variable, initial, update, extract)
  @generator = generator
  @variable = variable
  @initial = initial
  @update = update
  @extract = extract
end

Instance Attribute Details

#extractObject (readonly)

Returns the value of attribute extract.



726
727
728
# File 'lib/rjq/ast.rb', line 726

def extract
  @extract
end

#generatorObject (readonly)

Returns the value of attribute generator.



726
727
728
# File 'lib/rjq/ast.rb', line 726

def generator
  @generator
end

#initialObject (readonly)

Returns the value of attribute initial.



726
727
728
# File 'lib/rjq/ast.rb', line 726

def initial
  @initial
end

#updateObject (readonly)

Returns the value of attribute update.



726
727
728
# File 'lib/rjq/ast.rb', line 726

def update
  @update
end

#variableObject (readonly)

Returns the value of attribute variable.



726
727
728
# File 'lib/rjq/ast.rb', line 726

def variable
  @variable
end

Instance Method Details

#eval(input, context) ⇒ Object



736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
# File 'lib/rjq/ast.rb', line 736

def eval(input, context)
  out = []
  @initial.eval(input, context).each do |initial|
    accumulators = [initial]
    @generator.eval(input, context).each do |value|
      ctx = AST.bind_pattern(context, @variable, value)
      next unless ctx
      accumulators = accumulators.flat_map { |accumulator| @update.eval(accumulator, ctx) }
      accumulators.each { |accumulator| out.concat(@extract ? @extract.eval(accumulator, ctx) : [accumulator]) }
    rescue BreakSignal => e
      raise BreakSignal.new(e.label, e.value, outputs: out + (e.outputs || []))
    end
  end
  out
end