Sha256: 23d16ff0a012dcc40379aaf564354ea8958fb12d398a18d0b951b160e4d76e46

Contents?: true

Size: 1.42 KB

Versions: 1

Compression:

Stored size: 1.42 KB

Contents

module Dry
  module BlackTie
    class << self
      def protocols
        @protocols ||= Hash.new { |h, k| h[k] = h.dup.clear }
      end

      def implementations
        @implementations ||= Hash.new { |h, k| h[k] = h.dup.clear }
      end
    end

    def defprotocol(delegate: [])
      raise if BlackTie.protocols.key?(self) # DUPLICATE DEF
      raise unless block_given? || !delegate.empty?
      # FIXME IMPLEMENT DELEGATES!
      raise unless block_given?

      ims = instance_methods(false)
      class_eval(&Proc.new)
      (instance_methods(false) - ims).each { |m| class_eval { module_function m } }

      BlackTie.protocols[self].each do |method, *_| # FIXME CHECK PARAMS CORRESPONDENCE HERE
        # receiver, *args = *args
        singleton_class.send :define_method, method do |receiver, *args|
          receiver.class.ancestors.lazy.map do |c|
            BlackTie.implementations[self].fetch(c, nil)
          end.reject(&:nil?).first[method].(receiver, *args)
        end
      end
    end

    def defmethod name, *params
      BlackTie.protocols[self][name] = params
    end

    def defimpl protocol = nil, **params
      raise unless block_given?
      raise if params[:for].nil?

      Module.new { singleton_class.class_eval(&Proc.new) }.tap do |mod|
        mod.methods(false).each do |m|
          BlackTie.implementations[protocol || self][params[:for]][m] = mod.method(m).to_proc
        end
      end
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
dry-behaviour-0.1.0 lib/dry/behaviour/black_tie.rb