lib/raap/value/interface.rb in raap-0.4.0 vs lib/raap/value/interface.rb in raap-0.5.0

- old
+ new

@@ -1,58 +1,84 @@ # frozen_string_literal: true module RaaP module Value class Interface < BasicObject - def initialize(type, size: 3, self_type: nil, instance_type: nil, class_type: nil) - @type = type.is_a?(::String) ? RBS.parse_type(type) : type - unless @type.instance_of?(::RBS::Types::Interface) - ::Kernel.raise ::TypeError, "not an interface type: #{@type}" - end - @size = size + class << self + def define_method_from_interface(base_class, type, size: 3) + type = type.is_a?(::String) ? RBS.parse_type(type) : type + unless type.instance_of?(::RBS::Types::Interface) + ::Kernel.raise ::TypeError, "not an interface type: #{type}" + end + self_type = type - @definition = RBS.builder.build_interface(@type.name.absolute!) - @definition.methods.each do |name, method| - method_type = method.method_types.sample or Kernel.raise - type_params = @definition.type_params_decl.concat(method_type.type_params.drop(@definition.type_params_decl.length)) - ts = TypeSubstitution.new(type_params, @type.args) + # Referring to Steep + instance_type = ::RBS::Types::ClassInstance.new(name: TypeName("::Object"), args: [], location: nil) + class_type = ::RBS::Types::ClassSingleton.new(name: TypeName("::Object"), location: nil) - subed_method_type = ts.method_type_sub(method_type, self_type:, instance_type:, class_type:) + definition = RBS.builder.build_interface(type.name.absolute!) + definition.methods.each do |name, method| + method_type = method.method_types.sample or ::Kernel.raise + type_params = definition.type_params_decl.concat(method_type.type_params.drop(definition.type_params_decl.length)) + ts = TypeSubstitution.new(type_params, type.args) + subed_method_type = ts.method_type_sub(method_type, self_type:, instance_type:, class_type:) - BindCall.define_singleton_method(self, name) do |*_, &b| - # @type var b: Proc? - @fixed_return_value ||= Type.new(subed_method_type.type.return_type).pick(size:) - if subed_method_type.block - @fixed_block_arguments ||= size.times.map do - fun_type = FunctionType.new(subed_method_type.block.type) - fun_type.pick_arguments(size:) + BindCall.define_method(base_class, name) do |*_, &b| + @fixed_return_value ||= {} + @fixed_return_value[name] ||= if self_type == subed_method_type.type.return_type + self + else + Type.new(subed_method_type.type.return_type).pick(size:) + end + # @type var b: Proc? + if b + @fixed_block_arguments ||= {} + @fixed_block_arguments[name] ||= if subed_method_type.block + size.times.map do + FunctionType.new(subed_method_type.block.type) + .pick_arguments(size:) + end + else + [] + end + @fixed_block_arguments[name].each do |a, kw| + b.call(*a, **kw) + end end - else - @fixed_block_arguments = [] + @fixed_return_value[name] end - if b - unless subed_method_type.block - Kernel.raise "block of `#{@type.name}##{name}` was called. But block signature not defined." - end - @fixed_block_arguments.each do |a, kw| - b.call(*a, **kw) - end - end - @fixed_return_value end end + + def new(type, size: 3) + temp_class = ::Class.new(Interface) do |c| + define_method_from_interface(c, type, size:) + end + instance = temp_class.allocate + instance.__send__(:initialize, type, size:) + instance + end end + def initialize(type, size: 3) + @type = type.is_a?(::String) ? RBS.parse_type(type) : type + unless @type.instance_of?(::RBS::Types::Interface) + ::Kernel.raise ::TypeError, "not an interface type: #{type}" + end + @definition = RBS.builder.build_interface(@type.name.absolute!) + @size = size + end + def respond_to?(name, _include_all = false) @definition.methods.has_key?(name.to_sym) end def class Interface end def inspect - "#<interface @type=#{@type} @methods=#{@definition.methods.keys} @size=#{@size}>" + "#<interface @type=`#{@type}` @methods=#{@definition.methods.keys} @size=#{@size}>" end end end end