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