class Steep::Interface::Function::Params::PositionalParams
def self.build(required:, optional:, rest:)
def self.build(required:, optional:, rest:) params = rest ? self.rest(rest) : nil params = optional.reverse_each.inject(params) {|params, type| self.optional(type, params) } params = required.reverse_each.inject(params) {|params, type| self.required(type, params) } params end
def self.merge_for_intersection(xs, ys)
Raises when failed.
Calculates xs & ys.
def self.merge_for_intersection(xs, ys) x = xs&.head y = ys&.head case when x.is_a?(Required) && y.is_a?(Required) xs or raise ys or raise required( intersection(x.type, y.type), merge_for_intersection(xs.tail, ys.tail) ) when x.is_a?(Required) && !y raise when x.is_a?(Required) && y.is_a?(Optional) xs or raise ys or raise required( intersection(x.type, y.type), merge_for_intersection(xs.tail, ys.tail) ) when x.is_a?(Required) && y.is_a?(Rest) xs or raise ys or raise required( intersection(x.type, y.type), merge_for_intersection(xs.tail, ys) ) when !x && y.is_a?(Required) raise when !x && !y nil when !x && y.is_a?(Optional) nil when !x && y.is_a?(Rest) nil when x.is_a?(Optional) && y.is_a?(Required) xs or raise ys or raise required( intersection(x.type, y.type), merge_for_intersection(xs.tail, ys.tail) ) when x.is_a?(Optional) && !y nil when x.is_a?(Optional) && y.is_a?(Optional) xs or raise ys or raise optional( intersection(x.type, y.type), merge_for_intersection(xs.tail, ys.tail) ) when x.is_a?(Optional) && y.is_a?(Rest) xs or raise ys or raise optional( intersection(x.type, y.type), merge_for_intersection(xs.tail, ys) ) when x.is_a?(Rest) && y.is_a?(Required) xs or raise ys or raise required( intersection(x.type, y.type), merge_for_intersection(xs, ys.tail) ) when x.is_a?(Rest) && !y nil when x.is_a?(Rest) && y.is_a?(Optional) xs or raise ys or raise optional( intersection(x.type, y.type), merge_for_intersection(xs, ys.tail) ) when x.is_a?(Rest) && y.is_a?(Rest) rest(intersection(x.type, y.type)) end end
def self.merge_for_overload(xs, ys)
Calculates xs + ys.
def self.merge_for_overload(xs, ys) x = xs&.head y = ys&.head case when x.is_a?(Required) && y.is_a?(Required) xs or raise ys or raise required( union(x.type, y.type), merge_for_overload(xs.tail, ys.tail) ) when x.is_a?(Required) && y.is_a?(Optional) xs or raise ys or raise optional( union(x.type, y.type, null: true), merge_for_overload(xs.tail, ys.tail) ) when x.is_a?(Required) && y.is_a?(Rest) xs or raise ys or raise optional( union(x.type, y.type, null: true), merge_for_overload(xs.tail, ys) ) when x.is_a?(Required) && !y xs or raise optional( union(x.type, null: true), merge_for_overload(xs.tail, nil) ) when x.is_a?(Optional) && y.is_a?(Required) xs or raise ys or raise optional( union(x.type, y.type, null: true), merge_for_overload(xs.tail, ys.tail) ) when x.is_a?(Optional) && y.is_a?(Optional) xs or raise ys or raise optional( union(x.type, y.type), merge_for_overload(xs.tail, ys.tail) ) when x.is_a?(Optional) && y.is_a?(Rest) xs or raise ys or raise optional( union(x.type, y.type), merge_for_overload(xs.tail, ys) ) when x.is_a?(Optional) && !y xs or raise optional( x.type, merge_for_overload(xs.tail, nil) ) # == xs when x.is_a?(Rest) && y.is_a?(Required) xs or raise ys or raise optional( union(x.type, y.type, null: true), merge_for_overload(xs, ys.tail) ) when x.is_a?(Rest) && y.is_a?(Optional) xs or raise ys or raise optional( union(x.type, y.type), merge_for_overload(xs, ys.tail) ) when x.is_a?(Rest) && y.is_a?(Rest) xs or raise ys or raise rest(union(x.type, y.type)) when x.is_a?(Rest) && !y xs or raise when !x && y.is_a?(Required) ys or raise optional( union(y.type, null: true), merge_for_overload(nil, ys.tail) ) when !x && y.is_a?(Optional) ys or raise optional( y.type, merge_for_overload(nil, ys.tail) ) # == ys when !x && y.is_a?(Rest) ys or raise when !x && !y nil end end
def self.merge_for_union(xs, ys)
def self.merge_for_union(xs, ys) x = xs&.head y = ys&.head case when x.is_a?(Required) && y.is_a?(Required) xs or raise ys or raise required( union(x.type, y.type), merge_for_union(xs.tail, ys.tail) ) when x.is_a?(Required) && !y xs or raise optional( x.type, merge_for_union(xs.tail, nil) ) when x.is_a?(Required) && y.is_a?(Optional) xs or raise ys or raise optional( union(x.type, y.type), merge_for_union(xs.tail, ys.tail) ) when x.is_a?(Required) && y.is_a?(Rest) xs or raise ys or raise optional( union(x.type, y.type), merge_for_union(xs.tail, ys) ) when !x && y.is_a?(Required) ys or raise optional( y.type, merge_for_union(nil, ys.tail) ) when !x && !y nil when !x && y.is_a?(Optional) ys or raise PositionalParams.new(head: y, tail: merge_for_union(nil, ys.tail)) when !x && y.is_a?(Rest) ys or raise when x.is_a?(Optional) && y.is_a?(Required) xs or raise ys or raise optional( union(x.type, y.type), merge_for_union(xs.tail, ys.tail) ) when x.is_a?(Optional) && !y xs or raise PositionalParams.new(head: x, tail: merge_for_union(xs.tail, nil)) # == xs when x.is_a?(Optional) && y.is_a?(Optional) xs or raise ys or raise optional( union(x.type, y.type), merge_for_union(xs.tail, ys.tail) ) when x.is_a?(Optional) && y.is_a?(Rest) xs or raise ys or raise optional( union(x.type, y.type), merge_for_union(xs.tail, ys.tail) ) when x.is_a?(Rest) && y.is_a?(Required) xs or raise ys or raise optional( union(x.type, y.type), merge_for_union(xs, ys.tail) ) when x.is_a?(Rest) && !y xs or raise when x.is_a?(Rest) && y.is_a?(Optional) xs or raise ys or raise optional( union(x.type, y.type), merge_for_union(xs, ys.tail) ) when x.is_a?(Rest) && y.is_a?(Rest) xs or raise ys or raise rest( union(x.type, y.type) ) end end
def self.optional(type, tail = nil)
def self.optional(type, tail = nil) PositionalParams.new(head: Optional.new(type), tail: tail) end
def self.required(type, tail = nil)
def self.required(type, tail = nil) PositionalParams.new(head: Required.new(type), tail: tail) end
def self.rest(type, tail = nil)
def self.rest(type, tail = nil) PositionalParams.new(head: Rest.new(type), tail: tail) end
def ==(other)
def ==(other) other.is_a?(PositionalParams) && other.head == head && other.tail == tail end
def each(&block)
def each(&block) if block yield head tail&.each(&block) else enum_for(:each) end end
def each_type
def each_type if block_given? each do |param| yield param.type end else enum_for :each_type end end
def hash
def hash self.class.hash ^ head.hash ^ tail.hash end
def initialize(head:, tail:)
def initialize(head:, tail:) @head = head @tail = tail end
def map(&block)
def map(&block) hd = yield(head) tl = tail&.map(&block) if head == hd && tail == tl self else PositionalParams.new(head: hd, tail: tl) end end
def map_type(&block)
def map_type(&block) if block map {|param| param.map_type(&block) } else enum_for :map_type end end
def size
def size 1 + (tail&.size || 0) end
def subst(s)
def subst(s) map_type do |type| ty = type.subst(s) if ty == type type else ty end end end
def to_ary
def to_ary [head, tail] end