Class: Mixture::Type

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/mixture/type.rb

Overview

A type. This can be represented as a constant. This is normally anything that inherits Class. One instance per type.

Constant Summary collapse

BooleanClass =
Class.new
InstanceClass =
Class.new
BUILTIN_TYPES =
%w(
  Object Array Hash Integer Rational Float Set String Symbol
  Time Date DateTime
).map(&:intern).freeze
TYPE_ALIASES =
{
  true => BooleanClass,
  false => BooleanClass,
  nil => NilClass,
  nil: NilClass,
  bool: BooleanClass,
  boolean: BooleanClass,
  str: ::String,
  string: ::String,
  int: ::Integer,
  integer: ::Integer,
  rational: ::Rational,
  float: ::Float,
  array: ::Array,
  set: ::Set,
  symbol: ::Symbol,
  time: ::Time,
  date_time: ::DateTime,
  date: ::Date
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type, options = {}) ⇒ Type

Returns a new instance of Type.



118
119
120
121
122
123
# File 'lib/mixture/type.rb', line 118

def initialize(type, options = {})
  fail ArgumentError, "Expected a Class, got #{type.class}" unless
    type.is_a?(Class)
  @type = type
  @name = options.fetch(:name, @type.name)
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



116
117
118
# File 'lib/mixture/type.rb', line 116

def name
  @name
end

Class Method Details

.[](type) ⇒ Mixture::Type

Returns a Mixture::Type from a given class. It assumes that the type given is a class, and passes it to #new - which will error if it isn’t.

Parameters:

  • type (Class)

    A type.

Returns:



59
60
61
# File 'lib/mixture/type.rb', line 59

def self.[](type)
  from(type)
end

.from(type) ⇒ Mixture::Type

Returns a Mixture::Type from a given class. It assumes that the type given is a class, and passes it to #new - which will error if it isn’t.

Parameters:

  • type (Class)

    A type.

Returns:



52
53
54
55
56
# File 'lib/mixture/type.rb', line 52

def self.from(type)
  @instances.fetch(type) do
    @instances[type] = new(type)
  end
end

.infer(value) ⇒ Mixture::Type

Determines the best type that represents the given value. If the given value is a Mixture::Type, it returns the value. If the given value is already defined as a Mixture::Type, it returns the Mixture::Type. If the value’s class is already defined as a Mixture::Type, it returns the class’s Mixture::Type; otherwise, it returns the types for Class and Object, depending on if the value is a Class or not, respectively.

Examples:

Mixture::Type.infer(Integer) # => Mixture::Type::Integer
Mixture::Type.infer(1) # => Mixture::Type::Integer
Mixture::Type.infer(MyClass) # => Mixture::Type::Instance
Mixture::Type.infer(Object.new) # => Mixture::Type::Object

Parameters:

  • value (Object)

    The value to infer.

Returns:



85
86
87
88
89
90
91
92
# File 'lib/mixture/type.rb', line 85

def self.infer(value)
  case
  when TYPE_ALIASES.key?(value) then from(TYPE_ALIASES[value])
  when value.is_a?(Type)        then value
  when value.is_a?(Class)       then infer_class(value)
  else infer_class(value.class)
  end
end

.infer_class(klass) ⇒ Object



94
95
96
97
98
99
100
101
# File 'lib/mixture/type.rb', line 94

def self.infer_class(klass)
  if klass.is_a?(Type)
    klass
  else
    basic_ancestors = klass.ancestors - ancestors
    from(basic_ancestors.find { |a| @instances.key?(a) } || klass)
  end
end

.loadObject



103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/mixture/type.rb', line 103

def self.load
  BUILTIN_TYPES.each do |sym|
    const_set(sym, from(::Object.const_get(sym)))
  end

  @instances[BooleanClass] = new(BooleanClass, name: "Boolean")
  const_set("Boolean", @instances[BooleanClass])
  @instances[InstanceClass] = new(InstanceClass, name: "Instance")
  const_set("Instance", @instances[InstanceClass])
  @instances[NilClass] = new(NilClass, name: "Nil")
  const_set("Nil", @instances[NilClass])
end

Instance Method Details

#method_nameObject



130
131
132
133
134
135
136
137
138
# File 'lib/mixture/type.rb', line 130

def method_name
  @_method_name ||= begin
    body = name
           .gsub(/^([A-Z])/) { |m| m.downcase }
           .gsub(/::([A-Z])/) { |_, m| "_#{m.downcase}" }
           .gsub(/([A-Z])/) { |m| "_#{m.downcase}" }
    :"to_#{body}"
  end
end

#to_sObject Also known as: inspect



125
126
127
# File 'lib/mixture/type.rb', line 125

def to_s
  "#{self.class.name}(#{@name})"
end