module Taipo::Utilities
Utility methods for Taipo
@since 1.4.0 @api private
Public Class Methods
Return a named variable from either an object or a binding
@param name [String] the name of the variable @param object [Object] the object in which the variable may exist @param context [Binding] the binding in which the variable may exist
@return [Object] the variable
@raise [Taipo::NameError] if no variable with name
exists
@since 1.5.0 @api private
# File lib/taipo/utilities.rb, line 24 def self.extract_variable(name:, object:, context:) if name[0] == '@' && object.instance_variable_defined?(name) object.instance_variable_get name elsif name[0] != '@' && context.local_variable_defined?(name) context.local_variable_get name else msg = "Argument '#{name}' is not defined." raise Taipo::NameError, msg end end
Check
if a string is the name of an instance method
@note All this does is check whether the given string begins with a hash
symbol.
@param str [String] the string to check
@return [Boolean] the result
@since 1.4.0 @api private
# File lib/taipo/utilities.rb, line 46 def self.instance_method?(str) str[0] == '#' end
Check
if an object matches a given type definition
@param object [Object] the object to check @param definition [String] the type definiton to check against
@return [Boolean] the result
@raise [::TypeError] if definition
is not a String @raise [Taipo::SyntaxError] if the type definitions in checks
are
invalid
@since 1.5.0 @api private
# File lib/taipo/utilities.rb, line 63 def self.match?(object:, definition:) msg = "The 'definition' argument must be of type String." raise ::TypeError, msg unless definition.is_a? String types = Taipo::Parser.parse definition types.any? { |t| t.match? object } end
Return the type definition for an object
@note This assume that each element returned by Enumerator#each has the same
number of components.
@param obj [Object] the object
@return [String] a type definition of the object
@since 1.4.0 @api private
# File lib/taipo/utilities.rb, line 82 def self.object_to_type_def(obj) return obj.class.name unless obj.is_a? Enumerable if obj.is_a? Array element_types = Hash.new obj.each { |o| element_types[self.object_to_type_def(o)] = true } if element_types.empty? obj.class.name else obj.class.name + '<' + element_types.keys.join('|') + '>' end else element_types = Array.new obj.each.with_index do |element,index_e| element.each.with_index do |component,index_c| element_types[index_c] = Hash.new if index_e == 0 c_type = self.object_to_type_def(component) element_types[index_c][c_type] = true end end inner = element_types.reduce('') do |memo,e| e_type = e.keys.join('|') (memo == '') ? e_type : memo + ',' + e_type end if element_types.empty? obj.class.name else obj.class.name + '<' + inner + '>' end end end
Check
if a string is the name of a symbol
@note All this does is check whether the given string begins with a colon.
@param str [String] the string to check
@return [Boolean] the result
@since 1.4.0 @api private
# File lib/taipo/utilities.rb, line 124 def self.symbol?(str) str[0] == ':' end
Throw an error with an appropriate message for a given object not matching a given type definition
@param object [Object] the object that does not match definition
@param name [String] the name of the object (with the code that originally
called the #check method)
@param definition [String] the type definition that does not match object
@param result [Boolean] whether this is being called in respect of a
return value (such as by {Taipo::Result::ClassMethods#result})
@raise [Taipo::TypeError] the error
@since 1.5.0 @api private
# File lib/taipo/utilities.rb, line 142 def self.throw_error(object:, name:, definition:, result: false) subject = (result) ? "The return value of #{name}" : "Object '#{name}'" if Taipo::Utilities.instance_method? definition msg = "#{subject} does not respond to #{definition}." elsif Taipo::Utilities.symbol? definition msg = "#{subject} is not equal to #{definition}." elsif object.is_a? Enumerable type_def = Taipo::Utilities.object_to_type_def object msg = "#{subject} is #{type_def} but expected #{definition}." else class_name = object.class.name msg = "#{subject} is #{class_name} but expected #{definition}." end raise Taipo::TypeError, msg end