lib/raap/value/intersection.rb in raap-0.4.0 vs lib/raap/value/intersection.rb in raap-0.5.0
- old
+ new
@@ -1,47 +1,40 @@
# frozen_string_literal: true
module RaaP
module Value
- class Intersection < BasicObject
- def initialize(type, size: 3)
- @type = type.is_a?(::String) ? RBS.parse_type(type) : type
- unless @type.instance_of?(::RBS::Types::Intersection)
- ::Kernel.raise ::TypeError, "not an intersection type: #{@type}"
+ module Intersection
+ # Build an object to realize an intersection.
+ def self.new(type, size: 3)
+ type = type.is_a?(::String) ? RBS.parse_type(type) : type
+ unless type.instance_of?(::RBS::Types::Intersection)
+ ::Kernel.raise ::TypeError, "not an intersection type: #{type}"
end
- @children = @type.types.map { |t| Type.new(t).pick(size:) }
- @size = size
- end
+ instances = type.types.filter_map do |t|
+ t.instance_of?(::RBS::Types::ClassInstance) && Object.const_get(t.name.absolute!.to_s)
+ end
+ instances.uniq!
+ unless instances.count { |c| c.is_a?(::Class) } <= 1
+ raise ArgumentError, "intersection type must have at least one class instance type in `#{instances}`"
+ end
- def inspect
- "#<intersection @type.to_s=#{@type.to_s.inspect} @size=#{@size.inspect}>"
- end
+ base = instances.find { |c| c.is_a?(::Class) } || BasicObject
- def class
- Intersection
- end
+ c = Class.new(base) do
+ instances.select { |i| !i.is_a?(::Class) }.each do |m|
+ include(m)
+ end
- def method_missing(name, *args, **kwargs, &block)
- if respond_to?(name)
- @children.each do |child|
- if BindCall.respond_to?(child, name)
- return child.__send__(name, *args, **kwargs, &block)
- end
+ interfaces = type.types.select do |t|
+ t.instance_of?(::RBS::Types::Interface)
end
- ::Kernel.raise
- else
- super
- end
- end
- def respond_to?(name, include_all = false)
- @children.any? do |child|
- if BindCall.instance_of?(child, ::BasicObject)
- BindCall.respond_to?(child, name, include_all)
- else
- child.respond_to?(name, include_all)
+ interfaces.each do |interface|
+ Interface.define_method_from_interface(self, interface, size:)
end
end
+ type = ::RBS::Types::ClassInstance.new(name: TypeName(base.name), args: [], location: nil)
+ SymbolicCaller.new(Type.call_new_from(c, type, size:)).eval
end
end
end
end