lib/kind.rb in kind-0.6.0 vs lib/kind.rb in kind-1.0.0

- old
+ new

@@ -24,23 +24,17 @@ def self.Module(value) value == ::Module || (value.is_a?(::Module) && !self.Class(value)) end end - class Checker - attr_reader :type - - def initialize(type) - @type = type - end - + module Checker def class?(value) - Kind::Is.call(@type, value) + Kind::Is.(__kind, value) end def instance?(value) - value.is_a?(@type) + value.is_a?(__kind) end def or_nil(value) return value if instance?(value) end @@ -57,67 +51,125 @@ return Class if object.nil? self.call(::Class, object) end - const_set(:Class, ::Class.new(Checker) do - def instance?(value) - Kind::Is.Class(value) - end + const_set(:Class, ::Module.new do + extend Checker - alias class? instance? - end.new(::Class).freeze) + def self.__kind; ::Class; end + def self.class?(value); Kind::Is.Class(value); end + + def self.instance?(value); class?(value); end + end) + def self.Module(object = nil) return Module if object.nil? self.call(::Module, object) end - const_set(:Module, ::Class.new(Checker) do - def instance?(value) - Kind::Is.Module(value) - end + const_set(:Module, ::Module.new do + extend Checker - alias class? instance? - end.new(::Module).freeze) + def self.__kind; ::Module; end + + def self.class?(value); Kind::Is.Module(value); end + + def self.instance?(value); class?(value); end + end) end module Types extend self + COLONS = '::'.freeze + KIND_OF = <<-RUBY - def self.%{name}(object = nil, options = {}) + def self.%{method_name}(object = nil, options = {}) default = options[:or] - return Kind::Of::%{name} if object.nil? && default.nil? + return Kind::Of::%{kind_name} if object.nil? && default.nil? - Kind::Of.call(::%{name}, (object || default), name: "%{name}".freeze) + Kind::Of.(::%{kind_name}, (object || default), name: "%{kind_name}".freeze) end RUBY KIND_IS = <<-RUBY - def self.%{name}(value) - Kind::Is.call(::%{name}, value) + def self.%{method_name}(value = nil) + return Kind::Is::%{kind_name} if value.nil? + + Kind::Is.(::%{kind_name}, value) end RUBY - private_constant :KIND_OF, :KIND_IS + private_constant :KIND_OF, :KIND_IS, :COLONS - def add(mod, name: nil) - mod_name = Kind.of.Module(mod).name - chk_name = name ? Kind::Of.(String, name) : mod_name + def add(kind, name: nil) + kind_name = Kind.of.Module(kind).name + checker = name ? Kind::Of.(String, name) : kind_name - unless Of.respond_to?(chk_name) - Of.instance_eval(KIND_OF % { name: chk_name }) - Of.const_set(chk_name, Checker.new(mod).freeze) + case + when checker.include?(COLONS) + add_kind_with_namespace(checker, method_name: name) + else + add_root(checker, kind_name, method_name: name, create_kind_is_mod: false) end + end - unless Is.respond_to?(chk_name) - Is.instance_eval(KIND_IS % { name: chk_name }) + private + + def add_root(checker, kind_name, method_name:, create_kind_is_mod:) + root_checker = method_name ? method_name : checker + root_kind_name = method_name ? method_name : kind_name + + add_kind(root_checker, root_kind_name, Kind::Of, Kind::Is, create_kind_is_mod) end - end + + def add_kind_with_namespace(checker, method_name:) + raise NotImplementedError if method_name + + const_names = checker.split(COLONS) + const_names.each_with_index do |const_name, index| + if index == 0 + add_root(const_name, const_name, method_name: nil, create_kind_is_mod: true) + else + add_node(const_names, index) + end + end + end + + def add_node(const_names, index) + namespace = const_names[0..(index-1)] + namespace_name = namespace.join(COLONS) + + kind_of_mod = Kind::Of.const_get(namespace_name) + kind_is_mod = Kind::Is.const_get(namespace_name) + + checker = const_names[index] + kind_name = const_names[0..index].join(COLONS) + + add_kind(checker, kind_name, kind_of_mod, kind_is_mod, true) + end + + def add_kind(checker, kind_name, kind_of_mod, kind_is_mod, create_kind_is_mod) + params = { method_name: checker, kind_name: kind_name } + + unless kind_of_mod.respond_to?(checker) + kind_checker = ::Module.new { extend Checker } + kind_checker.module_eval("def self.__kind; #{kind_name}; end") + + kind_of_mod.instance_eval(KIND_OF % params) + kind_of_mod.const_set(checker, kind_checker) + end + + unless kind_is_mod.respond_to?(checker) + kind_is_mod.instance_eval(KIND_IS % params) + kind_is_mod.const_set(checker, Module.new) if create_kind_is_mod + end + end end def self.is; Is; end def self.of; Of; end @@ -160,19 +212,21 @@ return bool if bool.is_a?(::TrueClass) || bool.is_a?(::FalseClass) raise Kind::Error.new('Boolean'.freeze, bool) end - const_set(:Boolean, ::Class.new(Checker) do - def class?(value) - Kind.is.Boolean(value) - end + const_set(:Boolean, ::Module.new do + extend Checker - def instance?(value) + def self.__kind; [TrueClass, FalseClass].freeze; end + + def self.class?(value); Kind.is.Boolean(value); end + + def self.instance?(value); value.is_a?(TrueClass) || value.is_a?(FalseClass) end - end.new([TrueClass, FalseClass].freeze).freeze) + end) # -- Lambda def self.Lambda(object = nil, options = {}) default = options[:or] @@ -184,14 +238,18 @@ return func if func.is_a?(::Proc) && func.lambda? raise Kind::Error.new('Lambda'.freeze, func) end - const_set(:Lambda, ::Class.new(Checker) do - def instance?(value) - value.is_a?(@type) && value.lambda? + const_set(:Lambda, ::Module.new do + extend Checker + + def self.__kind; ::Proc; end + + def self.instance?(value) + value.is_a?(__kind) && value.lambda? end - end.new(::Proc).freeze) + end) end private_constant :Checker end