Module: Literal

Defined in:
lib/literal.rb,
lib/literal/version.rb

Defined Under Namespace

Modules: Error, Null, Properties, Rails, Type, Types Classes: ArgumentError, Array, Data, DataStructure, Delegator, Enum, Failure, Flags, Flags16, Flags32, Flags64, Flags8, Hash, Object, Property, Railtie, Result, Set, Struct, Success, Tuple, TypeError, Value

Constant Summary collapse

Loader =
Zeitwerk::Loader.for_gem.tap do |loader|
	loader.ignore("#{__dir__}/literal/rails")
	loader.ignore("#{__dir__}/literal/railtie.rb")
	loader.ignore("#{__dir__}/ruby_lsp")

	loader.inflector.inflect(
		"json_data_type" => "JSONDataType"
	)

	loader.collapse("#{__dir__}/literal/flags")
	loader.collapse("#{__dir__}/literal/errors")

	loader.setup
end
VERSION =
"1.8.1"
Transforms =

A map of core types to transform Procs mapping to the new type.

{
	Integer => {
		abs: Integer,
		ceil: Integer,
		chr: String,
		denominator: Integer,
		even?: Literal::Types::BooleanType::Instance,
		floor: Integer,
		hash: Integer,
		inspect: String,
		integer?: true,
		magnitude: Integer,
		negative?: Literal::Types::BooleanType::Instance,
		next: Integer,
		numerator: Integer,
		odd?: Literal::Types::BooleanType::Instance,
		ord: Integer,
		positive?: Literal::Types::BooleanType::Instance,
		pred: Integer,
		round: Integer,
		size: Integer,
		succ: Integer,
		to_f: Float,
		to_i: Integer,
		to_int: Integer,
		to_r: Rational,
		to_s: String,
		truncate: Integer,
		zero?: Literal::Types::BooleanType::Instance,
	},
	String => {
		ascii_only?: Literal::Types::BooleanType::Instance,
		bytesize: Integer,
		capitalize: String,
		chomp: String,
		chop: String,
		downcase: String,
		dump: String,
		empty?: Literal::Types::BooleanType::Instance,
		hash: Integer,
		inspect: String,
		length: Integer,
		lstrip: String,
		ord: Integer,
		reverse: String,
		rstrip: String,
		scrub: String,
		size: Integer,
		strip: String,
		swapcase: String,
		to_str: String,
		upcase: String,
		valid_encoding?: Literal::Types::BooleanType::Instance,
		to_i: Integer,
	},
	Numeric => {
		to_i: Integer,
		to_f: Float,
		to_s: String,
	},
	Array => {
		size: Integer,
		length: Integer,
		empty?: Literal::Types::BooleanType::Instance,
		sort: Array,
		to_a: Array,
		to_ary: Array,
	},
	Hash => {
		empty?: Literal::Types::BooleanType::Instance,
		inspect: String,
		keys: Array,
		length: Integer,
		size: Integer,
		to_a: Array,
		to_h: Hash,
		to_s: String,
		values: Array,
	},
	Set => {
		empty?: Literal::Types::BooleanType::Instance,
		inspect: String,
		length: Integer,
		size: Integer,
		to_a: Array,
		to_s: String,
	},
	Float => {
		abs: Float,
		ceil: Integer,
		floor: Integer,
		nan?: Literal::Types::BooleanType::Instance,
		negative?: Literal::Types::BooleanType::Instance,
		positive?: Literal::Types::BooleanType::Instance,
		round: Integer,
		to_i: Integer,
		to_s: String,
		truncate: Integer,
		zero?: Literal::Types::BooleanType::Instance,
	},
	Symbol => {
		empty?: Literal::Types::BooleanType::Instance,
		inspect: String,
		length: Integer,
		size: Integer,
		to_s: String,
		to_sym: Symbol,
	},
	Range => {
		begin: Object,
		end: Object,
		exclude_end?: Literal::Types::BooleanType::Instance,
		first: Object,
		last: Object,
		max: Object,
		min: Object,
		size: Integer,
		to_a: Array,
		to_s: String,
	},
	Regexp => {
		casefold?: Literal::Types::BooleanType::Instance,
		inspect: String,
		source: String,
		to_s: String,
	},
	Time => {
		day: Integer,
		hour: Integer,
		inspect: String,
		min: Integer,
		month: Integer,
		sec: Integer,
		to_a: Array,
		to_f: Float,
		to_i: Integer,
		to_s: String,
		year: Integer,
	},
}.transform_values! { |it| it.transform_keys(&:to_proc).freeze }.freeze

Class Method Summary collapse

Class Method Details

.Array(type) ⇒ Object



64
65
66
# File 'lib/literal.rb', line 64

def self.Array(type)
	Literal::Array::Generic.new(type)
end

.BrandObject



80
81
82
# File 'lib/literal.rb', line 80

def self.Brand(...)
	Literal::Brand.new(...)
end

.check(value, type) ⇒ Object



84
85
86
87
88
89
90
91
92
93
# File 'lib/literal.rb', line 84

def self.check(value, type)
	if type === value
		true
	else
		context = Literal::TypeError::Context.new(expected: type, actual: value)
		type.record_literal_type_errors(context) if type.respond_to?(:record_literal_type_errors)
		yield context if block_given?
		raise Literal::TypeError.new(context:)
	end
end

.Delegator(*args, **kwargs, &block) ⇒ Object



48
49
50
51
52
53
54
55
56
# File 'lib/literal.rb', line 48

def self.Delegator(*args, **kwargs, &block)
	delegator_class = Class.new(Literal::Delegator)

	type = Literal::Types._Constraint(*args, **kwargs)
	delegator_class.define_method(:__type__) { type }

	delegator_class.class_eval(&block) if block
	delegator_class.freeze
end

.Enum(type) ⇒ Object



58
59
60
61
62
# File 'lib/literal.rb', line 58

def self.Enum(type)
	Class.new(Literal::Enum) do
		prop :value, type, :positional, reader: :public
	end
end

.Hash(key_type, value_type) ⇒ Object



72
73
74
# File 'lib/literal.rb', line 72

def self.Hash(key_type, value_type)
	Literal::Hash::Generic.new(key_type, value_type)
end

.Set(type) ⇒ Object



68
69
70
# File 'lib/literal.rb', line 68

def self.Set(type)
	Literal::Set::Generic.new(type)
end

.subtype?(type, supertype) ⇒ Boolean

Returns:

  • (Boolean)


95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/literal.rb', line 95

def self.subtype?(type, supertype)
	subtype = type

	subtype = subtype.block.call if Types::DeferredType === subtype

	return true if supertype == subtype

	case supertype
	when Literal::Type
		supertype >= subtype
	when Module
		case subtype
		when Module
			supertype >= subtype
		when Numeric
			Numeric >= supertype
		when String
			String >= supertype
		when Symbol
			Symbol >= supertype
		when ::Array
			::Array >= supertype
		when ::Hash
			::Hash >= supertype
		else
			false
		end
	when Range
		supertype.cover?(subtype)
	else
		false
	end
end

.Tuple(*types) ⇒ Object



76
77
78
# File 'lib/literal.rb', line 76

def self.Tuple(*types)
	Literal::Tuple::Generic.new(*types)
end

.Value(*args, **kwargs, &block) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/literal.rb', line 22

def self.Value(*args, **kwargs, &block)
	value_class = Class.new(Literal::Value)

	type = Literal::Types._Constraint(*args, **kwargs)
	value_class.define_method(:__type__) { type }

	if subtype?(type, Integer)
		value_class.alias_method :to_i, :value
	elsif subtype?(type, String)
		value_class.alias_method :to_s, :value
		value_class.alias_method :to_str, :value
	elsif subtype?(type, Array)
		value_class.alias_method :to_a, :value
		value_class.alias_method :to_ary, :value
	elsif subtype?(type, Hash)
		value_class.alias_method :to_h, :value
	elsif subtype?(type, Float)
		value_class.alias_method :to_f, :value
	elsif subtype?(type, Set)
		value_class.alias_method :to_set, :value
	end

	value_class.class_eval(&block) if block
	value_class.freeze
end