module Steep module TypeInference class BlockParams class Param attr_reader :var attr_reader :type attr_reader :value attr_reader :node def initialize(var:, type:, value:, node:) @var = var @type = type @value = value @node = node end def ==(other) other.is_a?(Param) && other.var == var && other.type == type && other.value == value && other.node == node end alias eql? == def hash self.class.hash ^ var.hash ^ type.hash ^ value.hash ^ node.hash end end attr_reader :params attr_reader :rest def initialize(params:, rest:) @params = params @rest = rest end def self.from_node(node, annotations:) params = [] rest = nil node.children.each do |arg| var = arg.children.first type = annotations.lookup_var_type(var.name) case arg.type when :arg, :procarg0 params << Param.new(var: var, type: type, value: nil, node: arg) when :optarg params << Param.new(var: var, type: type, value: arg.children.last, node: arg) when :restarg rest = Param.new(var: var, type: type, value: nil, node: arg) end end new( params: params, rest: rest ) end def zip(params_type) [].tap do |zip| types = params_type.flat_unnamed_params params.each do |param| type = types.shift&.last || params_type.rest || AST::Types::Any.new if type zip << [param, type] end end if rest if types.empty? array = AST::Types::Name.new_instance( name: :Array, args: [params_type.rest || AST::Types::Any.new] ) zip << [rest, array] else union = AST::Types::Union.build(types: types.map(&:last) + [params_type.rest]) array = AST::Types::Name.new_instance( name: :Array, args: [union] ) zip << [rest, array] end end end end def each(&block) if block_given? params.each &block yield rest if rest else enum_for :each end end end end end