-
-
Notifications
You must be signed in to change notification settings - Fork 29
Expand file tree
/
Copy pathliteral.rb
More file actions
135 lines (110 loc) Β· 3.05 KB
/
Copy pathliteral.rb
File metadata and controls
135 lines (110 loc) Β· 3.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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
128
129
130
131
132
133
134
135
# frozen_string_literal: true
require "zeitwerk"
require_relative "literal/version"
module Literal
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
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
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
def self.Enum(type)
Class.new(Literal::Enum) do
prop :value, type, :positional, reader: :public
end
end
def self.Array(type)
Literal::Array::Generic.new(type)
end
def self.Set(type)
Literal::Set::Generic.new(type)
end
def self.Hash(key_type, value_type)
Literal::Hash::Generic.new(key_type, value_type)
end
def self.Tuple(*types)
Literal::Tuple::Generic.new(*types)
end
def self.Brand(...)
Literal::Brand.new(...)
end
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
def self.subtype?(type, supertype)
subtype = type
subtype = subtype.block.call if Types::DeferredType === subtype
supertype = supertype.block.call if Types::DeferredType === supertype
return true if subtype == Types::NeverType::Instance
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
when Literal::Type
subtype <= supertype
else
false
end
when Range
supertype.cover?(subtype)
else
false
end
end
end
require_relative "literal/railtie" if defined?(Rails)