moduleSteepmoduleInterfaceclassMethodTypeattr_reader:type_paramsattr_reader:typeattr_reader:blockattr_reader:method_declsdefinitialize(type_params:,type:,block:,method_decls:)@type_params=type_params@type=type@block=block@method_decls=method_declsenddef==(other)other.is_a?(self.class)&&other.type_params==type_params&&other.type==type&&other.block==blockendaliaseql?==defhashtype_params.hash^type.hash^block.hashenddeffree_variables@fvs||=Set.new.tapdo|set|set.merge(type.free_variables)ifblockset.merge(block.free_variables)endset.subtract(type_params)endenddefsubst(s)returnselfifs.empty?returnselfiffree_variables.disjoint?(s.domain)s_=s.except(type_params)self.class.new(type_params: type_params,type: type.subst(s_),block: block&.subst(s_),method_decls: method_decls)enddefeach_type(&block)ifblock_given?type.each_type(&block)self.block&.tapdoself.block.type.params.each_type(&block)yield(self.block.type.return_type)endelseenum_for:each_typeendenddefinstantiate(s)self.class.new(type_params: [],type: type.subst(s),block: block&.subst(s),method_decls: method_decls)enddefwith(type_params: self.type_params,type: self.type,block: self.block,method_decls: self.method_decls)self.class.new(type_params: type_params,type: type,block: block,method_decls: method_decls)enddefto_stype_params=!self.type_params.empty??"[#{self.type_params.map{|x|"#{x}"}.join(",")}] ":""params=type.params.to_sreturn_type=type.return_typeblock=self.block?" #{self.block}":"""#{type_params}#{params}#{block} -> #{return_type}"enddefmap_type(&block)self.class.new(type_params: type_params,type: type.map_type(&block),block: self.block&.yield_self{|blk|blk.map_type(&block)},method_decls: method_decls)end# Returns a new method type which can be used for the method implementation type of both `self` and `other`.#defunify_overload(other)type_params=[]s1=Substitution.build(self.type_params)type_params.push(*s1.dictionary.values.map(&:name))s2=Substitution.build(other.type_params)type_params.push(*s2.dictionary.values.map(&:name))block=casewhenself.block&&other.blockself.block.subst(s1)+other.block.subst(s2)whenself.blockself.block.to_optional.subst(s1)whenother.blockother.block.to_optional.subst(s2)endself.class.new(type_params: type_params,type: Function.new(params: type.params.subst(s1)+other.type.params.subst(s2),return_type: AST::Types::Union.build(types: [type.return_type.subst(s1),other.type.return_type.subst(s2)]),location: nil),block: block,method_decls: method_decls+other.method_decls)enddef+(other)unify_overload(other)end# Returns a method type which is a super-type of both self and other.# self <: (self | other) && other <: (self | other)## Returns nil if self and other are incompatible.#def|(other)self_type_params=Set.new(self.type_params)other_type_params=Set.new(other.type_params)unless(common_type_params=(self_type_params&other_type_params).to_a).empty?fresh_types=common_type_params.map{|name|AST::Types::Var.fresh(name)}fresh_names=fresh_types.map(&:name)subst=Substitution.build(common_type_params,fresh_types)other=other.instantiate(subst)type_params=(self_type_params+(other_type_params-common_type_params+Set.new(fresh_names))).to_aelsetype_params=(self_type_params+other_type_params).to_aendparams=self.type.params&other.type.paramsorreturnblock=casewhenself.block&&other.blockblock_params=self.block.type.params|other.block.type.paramsblock_return_type=AST::Types::Intersection.build(types: [self.block.type.return_type,other.block.type.return_type])block_type=Function.new(params: block_params,return_type: block_return_type,location: nil)Block.new(type: block_type,optional: self.block.optional&&other.block.optional)whenself.block&&self.block.optional?self.blockwhenother.block&&other.block.optional?other.blockwhen!self.block&&!other.blocknilelsereturnendreturn_type=AST::Types::Union.build(types: [self.type.return_type,other.type.return_type])MethodType.new(type_params: type_params,type: Function.new(params: params,return_type: return_type,location: nil),block: block,method_decls: method_decls+other.method_decls)end# Returns a method type which is a sub-type of both self and other.# (self & other) <: self && (self & other) <: other## Returns nil if self and other are incompatible.#def&(other)self_type_params=Set.new(self.type_params)other_type_params=Set.new(other.type_params)unless(common_type_params=(self_type_params&other_type_params).to_a).empty?fresh_types=common_type_params.map{|name|AST::Types::Var.fresh(name)}fresh_names=fresh_types.map(&:name)subst=Substitution.build(common_type_params,fresh_types)other=other.subst(subst)type_params=(self_type_params+(other_type_params-common_type_params+Set.new(fresh_names))).to_aelsetype_params=(self_type_params+other_type_params).to_aendparams=self.type.params|other.type.paramsblock=casewhenself.block&&other.blockblock_params=self.block.type.params&other.block.type.paramsorreturnblock_return_type=AST::Types::Union.build(types: [self.block.type.return_type,other.block.type.return_type])block_type=Function.new(params: block_params,return_type: block_return_type,location: nil)Block.new(type: block_type,optional: self.block.optional||other.block.optional)elseself.block||other.blockendreturn_type=AST::Types::Intersection.build(types: [self.type.return_type,other.type.return_type])MethodType.new(type_params: type_params,type: Function.new(params: params,return_type: return_type,location: nil),block: block,method_decls: method_decls+other.method_decls)endendendend