raap 0.3.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +31 -0
- data/README.md +32 -3
- data/Rakefile +10 -1
- data/exe/raap +4 -1
- data/lib/raap/bind_call.rb +21 -7
- data/lib/raap/cli.rb +211 -125
- data/lib/raap/function_type.rb +14 -10
- data/lib/raap/method_property.rb +60 -28
- data/lib/raap/method_type.rb +13 -6
- data/lib/raap/minitest.rb +9 -3
- data/lib/raap/rbs.rb +19 -0
- data/lib/raap/result.rb +84 -8
- data/lib/raap/sized.rb +2 -0
- data/lib/raap/symbolic_caller.rb +38 -26
- data/lib/raap/type.rb +111 -115
- data/lib/raap/type_substitution.rb +5 -1
- data/lib/raap/value/bottom.rb +2 -0
- data/lib/raap/value/interface.rb +61 -27
- data/lib/raap/value/intersection.rb +26 -21
- data/lib/raap/value/module.rb +50 -7
- data/lib/raap/value/top.rb +2 -0
- data/lib/raap/value/variable.rb +12 -1
- data/lib/raap/value/void.rb +2 -0
- data/lib/raap/version.rb +1 -1
- data/lib/raap.rb +3 -2
- data/public/jacket.webp +0 -0
- data/rbs_collection.lock.yaml +61 -1
- data/rbs_collection.yaml +0 -1
- data/sig/raap.rbs +63 -34
- data/sig/shims.rbs +4 -0
- metadata +10 -9
data/lib/raap/type.rb
CHANGED
@@ -13,25 +13,61 @@ module RaaP
|
|
13
13
|
|
14
14
|
def self.positive_float
|
15
15
|
x = Random.rand
|
16
|
-
x / Math.sqrt(1 - x * x)
|
16
|
+
x / Math.sqrt(1 - (x * x))
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
20
|
GENERATORS = {}
|
21
21
|
SIMPLE_SOURCE = ('a'..'z').to_a << '_'
|
22
|
-
RECURSION = Hash.new { |h, k| h[k] = { count: 0, logged: false } }
|
23
22
|
|
24
23
|
# Type.register "::Integer::positive" { sized { |size| size } }
|
25
24
|
def self.register(type_name, &block)
|
26
25
|
raise ArgumentError, "block is required" unless block
|
26
|
+
|
27
27
|
GENERATORS[type_name] = __skip__ = block
|
28
28
|
end
|
29
29
|
|
30
|
+
def self.random
|
31
|
+
Type.new("Integer | Float | Rational | Complex | String | Symbol | bool | Encoding | BasicObject | nil | Time")
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.random_without_basic_object
|
35
|
+
random.tap do |r|
|
36
|
+
# @type var rtype: ::RBS::Types::Union
|
37
|
+
rtype = r.type
|
38
|
+
rtype.types.reject! { |t| t.to_s == "BasicObject" }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.call_new_from(base, type, size:)
|
43
|
+
type_name = type.name.absolute!
|
44
|
+
definition = RBS.builder.build_singleton(type_name)
|
45
|
+
snew = definition.methods[:new]
|
46
|
+
if snew
|
47
|
+
# class
|
48
|
+
rbs_method_type = snew.method_types.sample or raise
|
49
|
+
type_params = definition.type_params_decl.concat(rbs_method_type.type_params.drop(definition.type_params_decl.length))
|
50
|
+
ts = TypeSubstitution.new(type_params, type.args)
|
51
|
+
maped_rbs_method_type = ts.method_type_sub(rbs_method_type)
|
52
|
+
method_type = MethodType.new(maped_rbs_method_type)
|
53
|
+
|
54
|
+
begin
|
55
|
+
args, kwargs, block = method_type.arguments_to_symbolic_call(size:)
|
56
|
+
[:call, base, :new, args, kwargs, block]
|
57
|
+
rescue
|
58
|
+
$stderr.puts "Fail with `#{rbs_method_type}`"
|
59
|
+
raise
|
60
|
+
end
|
61
|
+
else
|
62
|
+
[:call, Value::Module, :new, [type.to_s], { size: }, nil]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
30
66
|
# Special class case
|
31
67
|
register("::Array") do
|
32
|
-
|
33
|
-
t =
|
34
|
-
array(
|
68
|
+
instance = __skip__ = type
|
69
|
+
t = instance.args[0] ? Type.new(instance.args[0], range:) : Type.random
|
70
|
+
array(t)
|
35
71
|
end
|
36
72
|
register("::Binding") { sized { binding } }
|
37
73
|
register("::Complex") { complex }
|
@@ -40,14 +76,10 @@ module RaaP
|
|
40
76
|
register("::FalseClass") { sized { false } }
|
41
77
|
register("::Float") { float }
|
42
78
|
register("::Hash") do
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
v = _type.args[1] || 'untyped'
|
48
|
-
[Type.new(k).pick(size: size), Type.new(v).pick(size: size)]
|
49
|
-
end
|
50
|
-
end
|
79
|
+
instance = __skip__ = type
|
80
|
+
key = instance.args[0] ? Type.new(instance.args[0]) : Type.random_without_basic_object
|
81
|
+
value = instance.args[1] ? Type.new(instance.args[1]) : Type.random
|
82
|
+
dict(key, value)
|
51
83
|
end
|
52
84
|
register("::Integer") { integer }
|
53
85
|
register("::IO") { sized { $stdout } }
|
@@ -55,11 +87,11 @@ module RaaP
|
|
55
87
|
register("::NilClass") { sized { nil } }
|
56
88
|
register("::Proc") { sized { Proc.new {} } }
|
57
89
|
register("::Rational") { rational }
|
58
|
-
register("::Regexp") { sized { |size| Regexp.new(string.pick(size:
|
90
|
+
register("::Regexp") { sized { |size| Regexp.new(string.pick(size:)) } }
|
59
91
|
register("::String") { string }
|
60
92
|
register("::Struct") { sized { Struct.new(:foo, :bar).new } }
|
61
93
|
register("::Symbol") { symbol }
|
62
|
-
register("::Time") { sized { Time
|
94
|
+
register("::Time") { sized { [:call, Time, :now, [], {}, nil] } }
|
63
95
|
register("::TrueClass") { sized { true } }
|
64
96
|
register("::UnboundMethod") { sized { temp_method_object.unbind } }
|
65
97
|
|
@@ -79,15 +111,18 @@ module RaaP
|
|
79
111
|
|
80
112
|
def sized(&block)
|
81
113
|
Sized.new(&block).tap do |sized|
|
82
|
-
if s = @such_that
|
114
|
+
if (s = @such_that)
|
83
115
|
sized.such_that(&s)
|
84
116
|
end
|
85
117
|
end
|
86
118
|
end
|
87
119
|
|
88
|
-
def pick(size: 10
|
89
|
-
|
90
|
-
|
120
|
+
def pick(size: 10)
|
121
|
+
to_symbolic_caller(size:).eval
|
122
|
+
end
|
123
|
+
|
124
|
+
def to_symbolic_caller(size: 10)
|
125
|
+
SymbolicCaller.new(to_symbolic_call(size:))
|
91
126
|
end
|
92
127
|
|
93
128
|
def to_symbolic_call(size: 10)
|
@@ -96,15 +131,23 @@ module RaaP
|
|
96
131
|
|
97
132
|
case type
|
98
133
|
when ::RBS::Types::Tuple
|
99
|
-
type.types.map { |t| Type.new(t).
|
134
|
+
type.types.map { |t| Type.new(t).to_symbolic_call(size:) }
|
100
135
|
when ::RBS::Types::Union
|
101
|
-
type.types.sample&.then { |t| Type.new(t).
|
136
|
+
type.types.sample&.then { |t| Type.new(t).to_symbolic_call(size:) }
|
102
137
|
when ::RBS::Types::Intersection
|
103
|
-
|
138
|
+
if type.free_variables.empty?
|
139
|
+
[:call, Value::Intersection, :new, [type.to_s], { size: }, nil]
|
140
|
+
else
|
141
|
+
[:call, Value::Intersection, :new, [type], { size: }, nil]
|
142
|
+
end
|
104
143
|
when ::RBS::Types::Interface
|
105
|
-
|
144
|
+
if type.free_variables.empty?
|
145
|
+
[:call, Value::Interface, :new, [type.to_s], { size: }, nil]
|
146
|
+
else
|
147
|
+
[:call, Value::Interface, :new, [type], { size: }, nil]
|
148
|
+
end
|
106
149
|
when ::RBS::Types::Variable
|
107
|
-
[:call, Value::Variable, :new, [type], {}, nil]
|
150
|
+
[:call, Value::Variable, :new, [type.to_s], {}, nil]
|
108
151
|
when ::RBS::Types::Bases::Void
|
109
152
|
[:call, Value::Void, :new, [], {}, nil]
|
110
153
|
when ::RBS::Types::Bases::Top
|
@@ -113,72 +156,52 @@ module RaaP
|
|
113
156
|
[:call, Value::Bottom, :new, [], {}, nil]
|
114
157
|
when ::RBS::Types::Optional
|
115
158
|
case Random.rand(2)
|
116
|
-
in 0 then Type.new(type.type).
|
159
|
+
in 0 then Type.new(type.type).to_symbolic_call(size: size / 2)
|
117
160
|
in 1 then nil
|
118
161
|
end
|
119
162
|
when ::RBS::Types::Alias
|
120
163
|
case gen = GENERATORS[type.name.absolute!.to_s]
|
121
164
|
in Proc then instance_exec(&gen)
|
122
|
-
in nil then Type.new(RBS.builder.expand_alias2(type.name, type.args)).
|
165
|
+
in nil then Type.new(RBS.builder.expand_alias2(type.name, type.args)).to_symbolic_call(size:)
|
123
166
|
end
|
124
167
|
when ::RBS::Types::Bases::Class
|
125
|
-
|
168
|
+
RaaP.logger.warn("Unresolved `class` type, use Object instead.")
|
169
|
+
Object
|
126
170
|
when ::RBS::Types::Bases::Instance
|
127
|
-
|
171
|
+
RaaP.logger.warn("Unresolved `instance` type, use Object.new instead.")
|
172
|
+
Object.new
|
128
173
|
when ::RBS::Types::Bases::Self
|
129
174
|
raise "cannot resolve `self` type"
|
130
175
|
when ::RBS::Types::ClassSingleton
|
131
176
|
Object.const_get(type.name.to_s)
|
132
177
|
when ::RBS::Types::ClassInstance
|
133
178
|
case gen = GENERATORS[type.name.absolute!.to_s]
|
134
|
-
in Proc then instance_exec(&gen).pick(size:
|
135
|
-
in nil then
|
179
|
+
in Proc then instance_exec(&gen).pick(size:)
|
180
|
+
in nil then to_symbolic_call_from_initialize(type, size:)
|
136
181
|
end
|
137
182
|
when ::RBS::Types::Record
|
138
|
-
type.fields.transform_values { |t| Type.new(t).
|
183
|
+
type.fields.transform_values { |t| Type.new(t).to_symbolic_call(size: size / 2) }
|
139
184
|
when ::RBS::Types::Proc
|
140
|
-
Proc.new { Type.new(type.type.return_type).
|
185
|
+
Proc.new { Type.new(type.type.return_type).to_symbolic_call(size:) }
|
141
186
|
when ::RBS::Types::Literal
|
142
187
|
type.literal
|
143
188
|
when ::RBS::Types::Bases::Bool
|
144
|
-
bool.pick(size:
|
189
|
+
bool.pick(size:)
|
145
190
|
when ::RBS::Types::Bases::Any
|
146
|
-
|
191
|
+
Type.random.to_symbolic_call(size:)
|
147
192
|
when ::RBS::Types::Bases::Nil
|
148
193
|
nil
|
149
194
|
else
|
150
|
-
raise "not implemented #{type
|
195
|
+
raise "not implemented #{type}"
|
151
196
|
end
|
152
197
|
end
|
153
198
|
|
154
199
|
private
|
155
200
|
|
156
|
-
def
|
201
|
+
def to_symbolic_call_from_initialize(type, size:)
|
157
202
|
type_name = type.name.absolute!
|
158
203
|
const = Object.const_get(type_name.to_s)
|
159
|
-
|
160
|
-
snew = definition.methods[:new]
|
161
|
-
if snew
|
162
|
-
# class
|
163
|
-
rbs_method_type = snew.method_types.sample or raise
|
164
|
-
type_params = definition.type_params_decl.concat(rbs_method_type.type_params.drop(definition.type_params_decl.length))
|
165
|
-
ts = TypeSubstitution.new(type_params, type.args)
|
166
|
-
maped_rbs_method_type = rbs_method_type
|
167
|
-
maped_rbs_method_type = ts.method_type_sub(rbs_method_type)
|
168
|
-
method_type = MethodType.new(maped_rbs_method_type)
|
169
|
-
|
170
|
-
begin
|
171
|
-
try(times: 5, size: size) do |size|
|
172
|
-
args, kwargs, block = method_type.pick_arguments(size: size, eval: false)
|
173
|
-
[:call, const, :new, args, kwargs, block]
|
174
|
-
end
|
175
|
-
rescue
|
176
|
-
$stderr.puts "Fail with `#{rbs_method_type}`"
|
177
|
-
raise
|
178
|
-
end
|
179
|
-
else
|
180
|
-
[:call, Value::Module, :new, [type], {}, nil]
|
181
|
-
end
|
204
|
+
Type.call_new_from(const, type, size:)
|
182
205
|
end
|
183
206
|
|
184
207
|
def parse(type)
|
@@ -192,33 +215,8 @@ module RaaP
|
|
192
215
|
end
|
193
216
|
end
|
194
217
|
|
195
|
-
def try(times:, size:)
|
196
|
-
# @type var error: Exception?
|
197
|
-
ret = error = nil
|
198
|
-
times.times do
|
199
|
-
ret = yield size
|
200
|
-
if ret
|
201
|
-
error = nil
|
202
|
-
break
|
203
|
-
end
|
204
|
-
rescue => e
|
205
|
-
size += 1
|
206
|
-
error = e
|
207
|
-
next
|
208
|
-
end
|
209
|
-
|
210
|
-
if error
|
211
|
-
$stderr.puts
|
212
|
-
$stderr.puts "=== Catch error when generating type `#{type}`. Please check your RBS or RaaP bug. ==="
|
213
|
-
$stderr.puts "(#{error.class}) #{error.message}"
|
214
|
-
raise error
|
215
|
-
end
|
216
|
-
|
217
|
-
ret
|
218
|
-
end
|
219
|
-
|
220
218
|
def integer
|
221
|
-
sized { |size| float.pick(size:
|
219
|
+
sized { |size| float.pick(size:).round }
|
222
220
|
end
|
223
221
|
|
224
222
|
def none_zero_integer
|
@@ -231,9 +229,9 @@ module RaaP
|
|
231
229
|
in nil, nil
|
232
230
|
Arithmetic.float * size
|
233
231
|
in nil, high
|
234
|
-
high - Arithmetic.positive_float * size
|
232
|
+
high - (Arithmetic.positive_float * size)
|
235
233
|
in low, nil
|
236
|
-
low + Arithmetic.positive_float * size
|
234
|
+
low + (Arithmetic.positive_float * size)
|
237
235
|
in low, high
|
238
236
|
Random.rand(Range.new(low.to_f, high.to_f, @range.exclude_end?))
|
239
237
|
end.round(2)
|
@@ -242,16 +240,16 @@ module RaaP
|
|
242
240
|
|
243
241
|
def rational
|
244
242
|
sized do |size|
|
245
|
-
a = integer.pick(size:
|
246
|
-
b = none_zero_integer.pick(size:
|
243
|
+
a = integer.pick(size:)
|
244
|
+
b = none_zero_integer.pick(size:)
|
247
245
|
[:call, Kernel, :Rational, [a, b], {}, nil]
|
248
246
|
end
|
249
247
|
end
|
250
248
|
|
251
249
|
def complex
|
252
250
|
sized do |size|
|
253
|
-
a = integer.pick(size:
|
254
|
-
b = none_zero_integer.pick(size:
|
251
|
+
a = integer.pick(size:)
|
252
|
+
b = none_zero_integer.pick(size:)
|
255
253
|
[:call, Kernel, :Complex, [a, b], {}, nil]
|
256
254
|
end
|
257
255
|
end
|
@@ -262,13 +260,11 @@ module RaaP
|
|
262
260
|
+""
|
263
261
|
else
|
264
262
|
case [@range.begin, @range.end]
|
265
|
-
in nil, nil
|
263
|
+
in [nil, nil]
|
266
264
|
size.times.map { SIMPLE_SOURCE.sample }.join
|
267
|
-
in nil, _
|
268
|
-
raise "Should set range.begin and range.end"
|
269
|
-
in _, nil
|
265
|
+
in [nil, _] | [_, nil]
|
270
266
|
raise "Should set range.begin and range.end"
|
271
|
-
in s, e
|
267
|
+
in [s, e]
|
272
268
|
a = (s..e).to_a
|
273
269
|
size.times.map { a.sample }.join
|
274
270
|
end
|
@@ -278,14 +274,28 @@ module RaaP
|
|
278
274
|
|
279
275
|
def symbol
|
280
276
|
sized do |size|
|
281
|
-
string.pick(size:
|
277
|
+
string.pick(size:).to_sym
|
282
278
|
end
|
283
279
|
end
|
284
280
|
|
285
281
|
def array(type)
|
286
282
|
sized do |size|
|
287
|
-
Array.new(integer.pick(size:
|
288
|
-
type.
|
283
|
+
Array.new(integer.pick(size:).abs) do
|
284
|
+
type.to_symbolic_call(size: size / 2)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
# Create Hash object. But not `hash`.
|
290
|
+
# Avoid to use `hash` since core method name
|
291
|
+
def dict(key_type, value_type)
|
292
|
+
sized do |size|
|
293
|
+
csize = size / 2
|
294
|
+
Array.new(integer.pick(size:).abs).to_h do
|
295
|
+
[
|
296
|
+
key_type.to_symbolic_call(size: csize),
|
297
|
+
value_type.to_symbolic_call(size: csize)
|
298
|
+
]
|
289
299
|
end
|
290
300
|
end
|
291
301
|
end
|
@@ -293,7 +303,7 @@ module RaaP
|
|
293
303
|
def encoding
|
294
304
|
sized do
|
295
305
|
e = Encoding.list.sample or raise
|
296
|
-
[:call, Encoding, :find, [e.name], {}
|
306
|
+
[:call, Encoding, :find, [e.name], {}, nil]
|
297
307
|
end
|
298
308
|
end
|
299
309
|
|
@@ -303,24 +313,10 @@ module RaaP
|
|
303
313
|
end
|
304
314
|
end
|
305
315
|
|
306
|
-
def untyped
|
307
|
-
case Random.rand(9)
|
308
|
-
in 0 then integer
|
309
|
-
in 1 then float
|
310
|
-
in 2 then rational
|
311
|
-
in 3 then complex
|
312
|
-
in 4 then string
|
313
|
-
in 5 then symbol
|
314
|
-
in 6 then bool
|
315
|
-
in 7 then encoding
|
316
|
-
in 8 then sized { [:call, BasicObject, :new, [], {}, nil] }
|
317
|
-
end
|
318
|
-
end
|
319
|
-
|
320
316
|
def temp_method_object
|
321
317
|
o = Object.new
|
322
318
|
m = 6.times.map { SIMPLE_SOURCE.sample }.join
|
323
|
-
o.define_singleton_method(m) {
|
319
|
+
o.define_singleton_method(m) {}
|
324
320
|
o.method(m)
|
325
321
|
end
|
326
322
|
end
|
@@ -14,13 +14,16 @@ module RaaP
|
|
14
14
|
elsif bound.upper_bound
|
15
15
|
[bound.name, bound.upper_bound]
|
16
16
|
else
|
17
|
-
[bound.name, ::RBS::Types::
|
17
|
+
[bound.name, ::RBS::Types::Variable.new(name: bound.name, location: nil)]
|
18
18
|
end
|
19
19
|
end
|
20
20
|
::RBS::Substitution.build(bound_map.keys, bound_map.values)
|
21
21
|
end
|
22
22
|
|
23
23
|
def method_type_sub(method_type, self_type: nil, instance_type: nil, class_type: nil)
|
24
|
+
self_type = self_type.is_a?(::String) ? RBS.parse_type(self_type) : self_type
|
25
|
+
instance_type = instance_type.is_a?(::String) ? RBS.parse_type(instance_type) : instance_type
|
26
|
+
class_type = class_type.is_a?(::String) ? RBS.parse_type(class_type) : class_type
|
24
27
|
sub = build
|
25
28
|
::RBS::MethodType.new(
|
26
29
|
type_params: [],
|
@@ -36,6 +39,7 @@ module RaaP
|
|
36
39
|
if self_type.nil? && instance_type.nil? && class_type.nil?
|
37
40
|
return search
|
38
41
|
end
|
42
|
+
|
39
43
|
search.map_type do |ty|
|
40
44
|
case ty
|
41
45
|
when ::RBS::Types::Bases::Self
|
data/lib/raap/value/bottom.rb
CHANGED
data/lib/raap/value/interface.rb
CHANGED
@@ -3,39 +3,73 @@
|
|
3
3
|
module RaaP
|
4
4
|
module Value
|
5
5
|
class Interface < BasicObject
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
class << self
|
7
|
+
def define_method_from_interface(base_class, type, size: 3)
|
8
|
+
type = type.is_a?(::String) ? RBS.parse_type(type) : type
|
9
|
+
unless type.instance_of?(::RBS::Types::Interface)
|
10
|
+
::Kernel.raise ::TypeError, "not an interface type: #{type}"
|
11
|
+
end
|
12
|
+
self_type = type
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
type_params = definition.type_params_decl.concat(method_type.type_params.drop(definition.type_params_decl.length))
|
14
|
-
ts = TypeSubstitution.new(type_params, @type.args)
|
14
|
+
# Referring to Steep
|
15
|
+
instance_type = ::RBS::Types::ClassInstance.new(name: TypeName("::Object"), args: [], location: nil)
|
16
|
+
class_type = ::RBS::Types::ClassSingleton.new(name: TypeName("::Object"), location: nil)
|
15
17
|
|
16
|
-
|
18
|
+
definition = RBS.builder.build_interface(type.name.absolute!)
|
19
|
+
definition.methods.each do |name, method|
|
20
|
+
method_type = method.method_types.sample or ::Kernel.raise
|
21
|
+
type_params = definition.type_params_decl.concat(method_type.type_params.drop(definition.type_params_decl.length))
|
22
|
+
ts = TypeSubstitution.new(type_params, type.args)
|
23
|
+
subed_method_type = ts.method_type_sub(method_type, self_type:, instance_type:, class_type:)
|
17
24
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
25
|
+
BindCall.define_method(base_class, name) do |*_, &b|
|
26
|
+
@fixed_return_value ||= {}
|
27
|
+
@fixed_return_value[name] ||= if self_type == subed_method_type.type.return_type
|
28
|
+
self
|
29
|
+
else
|
30
|
+
Type.new(subed_method_type.type.return_type).pick(size:)
|
31
|
+
end
|
32
|
+
# @type var b: Proc?
|
33
|
+
if b
|
34
|
+
@fixed_block_arguments ||= {}
|
35
|
+
@fixed_block_arguments[name] ||= if subed_method_type.block
|
36
|
+
size.times.map do
|
37
|
+
FunctionType.new(subed_method_type.block.type)
|
38
|
+
.pick_arguments(size:)
|
39
|
+
end
|
40
|
+
else
|
41
|
+
[]
|
42
|
+
end
|
43
|
+
@fixed_block_arguments[name].each do |a, kw|
|
44
|
+
b.call(*a, **kw)
|
45
|
+
end
|
34
46
|
end
|
47
|
+
@fixed_return_value[name]
|
35
48
|
end
|
36
|
-
@fixed_return_value
|
37
49
|
end
|
38
50
|
end
|
51
|
+
|
52
|
+
def new(type, size: 3)
|
53
|
+
temp_class = ::Class.new(Interface) do |c|
|
54
|
+
define_method_from_interface(c, type, size:)
|
55
|
+
end
|
56
|
+
instance = temp_class.allocate
|
57
|
+
instance.__send__(:initialize, type, size:)
|
58
|
+
instance
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def initialize(type, size: 3)
|
63
|
+
@type = type.is_a?(::String) ? RBS.parse_type(type) : type
|
64
|
+
unless @type.instance_of?(::RBS::Types::Interface)
|
65
|
+
::Kernel.raise ::TypeError, "not an interface type: #{type}"
|
66
|
+
end
|
67
|
+
@definition = RBS.builder.build_interface(@type.name.absolute!)
|
68
|
+
@size = size
|
69
|
+
end
|
70
|
+
|
71
|
+
def respond_to?(name, _include_all = false)
|
72
|
+
@definition.methods.has_key?(name.to_sym)
|
39
73
|
end
|
40
74
|
|
41
75
|
def class
|
@@ -43,7 +77,7 @@ module RaaP
|
|
43
77
|
end
|
44
78
|
|
45
79
|
def inspect
|
46
|
-
"#<interface @type
|
80
|
+
"#<interface @type=`#{@type}` @methods=#{@definition.methods.keys} @size=#{@size}>"
|
47
81
|
end
|
48
82
|
end
|
49
83
|
end
|
@@ -2,33 +2,38 @@
|
|
2
2
|
|
3
3
|
module RaaP
|
4
4
|
module Value
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
module Intersection
|
6
|
+
# Build an object to realize an intersection.
|
7
|
+
def self.new(type, size: 3)
|
8
|
+
type = type.is_a?(::String) ? RBS.parse_type(type) : type
|
9
|
+
unless type.instance_of?(::RBS::Types::Intersection)
|
10
|
+
::Kernel.raise ::TypeError, "not an intersection type: #{type}"
|
11
|
+
end
|
12
|
+
instances = type.types.filter_map do |t|
|
13
|
+
t.instance_of?(::RBS::Types::ClassInstance) && Object.const_get(t.name.absolute!.to_s)
|
14
|
+
end
|
15
|
+
instances.uniq!
|
16
|
+
unless instances.count { |c| c.is_a?(::Class) } <= 1
|
17
|
+
raise ArgumentError, "intersection type must have at least one class instance type in `#{instances}`"
|
18
|
+
end
|
11
19
|
|
12
|
-
|
13
|
-
"#<intersection @type=#{@type.to_s.inspect} @size=#{@size.inspect}>"
|
14
|
-
end
|
20
|
+
base = instances.find { |c| c.is_a?(::Class) } || BasicObject
|
15
21
|
|
16
|
-
|
17
|
-
|
18
|
-
|
22
|
+
c = Class.new(base) do
|
23
|
+
instances.select { |i| !i.is_a?(::Class) }.each do |m|
|
24
|
+
include(m)
|
25
|
+
end
|
19
26
|
|
20
|
-
|
21
|
-
|
22
|
-
if BindCall.respond_to?(child, name)
|
23
|
-
return child.__send__(name, *args, **kwargs, &block)
|
27
|
+
interfaces = type.types.select do |t|
|
28
|
+
t.instance_of?(::RBS::Types::Interface)
|
24
29
|
end
|
25
|
-
end
|
26
|
-
end
|
27
30
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
+
interfaces.each do |interface|
|
32
|
+
Interface.define_method_from_interface(self, interface, size:)
|
33
|
+
end
|
31
34
|
end
|
35
|
+
type = ::RBS::Types::ClassInstance.new(name: TypeName(base.name), args: [], location: nil)
|
36
|
+
SymbolicCaller.new(Type.call_new_from(c, type, size:)).eval
|
32
37
|
end
|
33
38
|
end
|
34
39
|
end
|
data/lib/raap/value/module.rb
CHANGED
@@ -1,17 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RaaP
|
2
4
|
module Value
|
3
5
|
# FIXME: consider self_types
|
4
6
|
# HINT: intersection?
|
5
|
-
class Module
|
6
|
-
|
7
|
+
class Module < BasicObject
|
8
|
+
def initialize(type, size: 3)
|
9
|
+
@type = type.is_a?(::String) ? ::RaaP::RBS.parse_type(type) : type
|
10
|
+
@size = size
|
11
|
+
unless @type.instance_of?(::RBS::Types::ClassInstance)
|
12
|
+
::Kernel.raise ::TypeError, "not a module type: #{@type}"
|
13
|
+
end
|
14
|
+
|
15
|
+
one_instance_ancestors = ::RaaP::RBS.builder.ancestor_builder.one_instance_ancestors(@type.name.absolute!).self_types
|
16
|
+
@self_type = if one_instance_ancestors.nil? || one_instance_ancestors.empty?
|
17
|
+
::Object.new
|
18
|
+
else
|
19
|
+
one_instance_ancestors.map do |a_instance|
|
20
|
+
if a_instance.args.empty?
|
21
|
+
# : BasicObject
|
22
|
+
a_instance.name.absolute!.to_s
|
23
|
+
else
|
24
|
+
# : _Each[Integer]
|
25
|
+
args = a_instance.args.zip(@type.args).map do |_var, instance|
|
26
|
+
if instance
|
27
|
+
instance.to_s
|
28
|
+
else
|
29
|
+
'untyped'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
"#{a_instance.name}[#{args.map(&:to_s).join(', ')}]"
|
33
|
+
end
|
34
|
+
end.then do |ts|
|
35
|
+
if !ts.include?('::BasicObject') || ts.any? { |t| t.split('::').last&.start_with?('_') }
|
36
|
+
ts.unshift('Object')
|
37
|
+
end
|
38
|
+
Type.new(ts.uniq.join(' & ')).pick(size:)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
const = ::Object.const_get(@type.name.absolute!.to_s)
|
42
|
+
BindCall.extend(self, const)
|
43
|
+
end
|
44
|
+
|
45
|
+
def method_missing(name, *args, **kwargs, &block)
|
46
|
+
@self_type.__send__(name, *args, **kwargs, &block)
|
47
|
+
end
|
7
48
|
|
8
|
-
def
|
9
|
-
@
|
10
|
-
|
11
|
-
|
49
|
+
def respond_to?(name, include_all = false)
|
50
|
+
if BindCall.instance_of?(@self_type, ::BasicObject)
|
51
|
+
BindCall.respond_to?(@self_type, name, include_all)
|
52
|
+
else
|
53
|
+
@self_type.respond_to?(name, include_all)
|
54
|
+
end
|
12
55
|
end
|
13
56
|
|
14
|
-
def inspect = "#<module #{@type}>"
|
57
|
+
def inspect = "#<module #{@type} : #{BindCall.class(@self_type)} size=#{@size}>"
|
15
58
|
def class = Value::Module
|
16
59
|
end
|
17
60
|
end
|