#! ruby -Ks
#-- args_to_hash.rb
#-- args_to_hash.pi

def args_to_hash(args,key_array)
  ret = {}
  names = key_array.dup
  args.each{|a|
    if a.is_a?(Hash) && a.size==1 && a.keys[0].is_a?(Symbol)
      key,val = a.to_a[0]
      if item = names.find{|item|
            name,klass = ( item.is_a?(Hash) ? item.to_a[0] : item )
            klass = Object unless klass
            ( key == name )
          }
        name,klass = ( item.is_a?(Hash) ? item.to_a[0] : item )
        klass = Object unless klass
        raise ArgumentError, "'#{a.inspect}' must have a #{klass}" unless ( klass === val || val.nil? )
        names.delete(item)
        ret[key] = val
        next
      end

    else
      if a.is_a? Symbol
        key = a
        val = true
        if item = names.find{|item|
              name,klass = ( item.is_a?(Hash) ? item.to_a[0] : item )
              ( name === key )
            }
          name,klass = ( item.is_a?(Hash) ? item.to_a[0] : item )
          klass = Object unless klass
          raise ArgumentError, "'#{a.inspect}' must have a #{klass}" unless ( klass === true )
          names.delete(item)
          ret[key] = true
          next
        end
      end
      val = a
      if item = names.find{|item|
            name,klass = ( item.is_a?(Hash) ? item.to_a[0] : item )
            klass = Object unless klass
            ( klass === val )
          }
        name,klass = ( item.is_a?(Hash) ? item.to_a[0] : item )
        names.delete(item)
        ret[name] = val
        next
      end

    end
    ##raise ArgumentError, "unknown arg '#{a.inspect}'"
  }
  ret
end

if __FILE__ == $0

require "args_to_hash"

def test(*args)
  hash = args_to_hash(args,[
    {:arg1 => String},
    {:arg2 => Float},
    {:arg3 => Integer},
  ])
  return hash
end

p test(1,"two",3.0)
  #=> {:arg1=>"two", :arg2=>3.0, :arg3=>1}

def test(*args)
  hash = args_to_hash(args,[
    :arg1,
    :arg2,
    :arg3,
  ])
  return hash
end

p test(1,"two",3.0)
  #=> {:arg1=>1, :arg2=>"two", :arg3=>3.0}

end

