module Ruby
  # The way the ruby parser presents a call with a block is by wrapping the
  # whole thing in a :block scope. It includes the send and the block definition.
  #
  # A block is in essence quite like a method, so the block definition is like a
  # method definition, except it is not bound to the class direcly, but the enclosing
  # method. The enclosing method also provides the scope.
  class BlockStatement < Statement
    attr_reader :send ,  :args , :body

    def initialize( send , args , body )
      @send , @args , @body = send , args , body
      raise "no bod" unless @body
    end

    # In Vool we "hoist" the block definition through a local assignment, much
    # as we would other complex args (bit like in the Normalizer)
    # The block is then passed as a normal variable to the send. In other words, the
    # BlockStatement resolves to a list of Statements, the last of which is the send
    #
    def to_vool
      block_name = "implicit_block_#{object_id}".to_sym
      block = Vool::BlockStatement.new( @args.dup , @body.to_vool)
      assign = Vool::LocalAssignment.new( block_name , block)
      sendd = @send.to_vool
      if(sendd.is_a?(Vool::Statements))
        ret = sendd
        sendd = sendd.last
      else
        ret = Vool::Statements.new([sendd])
      end
      sendd.arguments << LocalVariable.new(block_name).to_vool
      ret.prepend(assign)
      ret
    end

  end
end