rigortype 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +215 -134
- data/data/builtins/ruby_core/comparable.yml +87 -0
- data/data/builtins/ruby_core/complex.yml +505 -0
- data/data/builtins/ruby_core/date.yml +1737 -0
- data/data/builtins/ruby_core/enumerable.yml +557 -0
- data/data/builtins/ruby_core/file.yml +9 -0
- data/data/builtins/ruby_core/rational.yml +365 -0
- data/data/builtins/ruby_core/string.yml +9 -0
- data/data/builtins/ruby_core/time.yml +6 -4
- data/lib/rigor/cli.rb +1 -1
- data/lib/rigor/inference/builtins/comparable_catalog.rb +27 -0
- data/lib/rigor/inference/builtins/complex_catalog.rb +41 -0
- data/lib/rigor/inference/builtins/date_catalog.rb +98 -0
- data/lib/rigor/inference/builtins/enumerable_catalog.rb +27 -0
- data/lib/rigor/inference/builtins/rational_catalog.rb +38 -0
- data/lib/rigor/inference/method_dispatcher/constant_folding.rb +126 -12
- data/lib/rigor/inference/method_dispatcher/iterator_dispatch.rb +99 -0
- data/lib/rigor/inference/method_dispatcher/kernel_dispatch.rb +95 -0
- data/lib/rigor/inference/method_dispatcher.rb +3 -1
- data/lib/rigor/inference/narrowing.rb +210 -1
- data/lib/rigor/inference/scope_indexer.rb +87 -11
- data/lib/rigor/inference/statement_evaluator.rb +5 -1
- data/lib/rigor/rbs_extended.rb +11 -6
- data/lib/rigor/type/integer_range.rb +4 -2
- data/lib/rigor/version.rb +1 -1
- data/sig/rigor/environment.rbs +4 -6
- data/sig/rigor/inference.rbs +2 -1
- data/sig/rigor/type.rbs +41 -41
- metadata +12 -1
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
# DO NOT EDIT — generated by tool/extract_builtin_catalog.rb
|
|
2
|
+
---
|
|
3
|
+
schema_version: 1
|
|
4
|
+
generated_from:
|
|
5
|
+
ruby_init_c: references/ruby/rational.c
|
|
6
|
+
ruby_prelude:
|
|
7
|
+
rbs:
|
|
8
|
+
- references/rbs/core/rational.rbs
|
|
9
|
+
purity_levels:
|
|
10
|
+
leaf: Prelude :leaf marker (VM-enforced) or C body uses no dispatch/yield/mutation.
|
|
11
|
+
trivial: Prelude method body is a literal return (self/true/false/nil/Integer).
|
|
12
|
+
leaf_when_numeric: C body falls through to rb_num_coerce_* only when an operand
|
|
13
|
+
is non-numeric; safe to fold when every argument is a concrete numeric.
|
|
14
|
+
inline_block: Prelude method carries :inline_block or :use_block; block-dependent.
|
|
15
|
+
block_dependent: C body yields or checks rb_block_given_p.
|
|
16
|
+
mutates_self: C body checks rb_check_frozen — typically a prelude to mutation.
|
|
17
|
+
dispatch: C body calls user-redefinable methods (rb_funcall*, rb_equal, rb_Float,
|
|
18
|
+
num_funcall*, etc).
|
|
19
|
+
unknown: C body not located in indexed C files.
|
|
20
|
+
classes:
|
|
21
|
+
Rational:
|
|
22
|
+
parent: Numeric
|
|
23
|
+
defined_at: references/ruby/rational.c:2758
|
|
24
|
+
includes: []
|
|
25
|
+
constants: {}
|
|
26
|
+
aliases: {}
|
|
27
|
+
instance_methods:
|
|
28
|
+
numerator:
|
|
29
|
+
source: c
|
|
30
|
+
cfunc: nurat_numerator
|
|
31
|
+
arity: 0
|
|
32
|
+
defined_at: references/ruby/rational.c:2767
|
|
33
|
+
c_body_at: references/ruby/rational.c:586
|
|
34
|
+
c_effects: []
|
|
35
|
+
purity: leaf
|
|
36
|
+
rbs:
|
|
37
|
+
- "() -> Integer"
|
|
38
|
+
rbs_at: references/rbs/core/rational.rbs:342
|
|
39
|
+
denominator:
|
|
40
|
+
source: c
|
|
41
|
+
cfunc: nurat_denominator
|
|
42
|
+
arity: 0
|
|
43
|
+
defined_at: references/ruby/rational.c:2768
|
|
44
|
+
c_body_at: references/ruby/rational.c:604
|
|
45
|
+
c_effects: []
|
|
46
|
+
purity: leaf
|
|
47
|
+
rbs:
|
|
48
|
+
- "() -> Integer"
|
|
49
|
+
rbs_at: references/rbs/core/rational.rbs:250
|
|
50
|
+
"-@":
|
|
51
|
+
source: c
|
|
52
|
+
cfunc: rb_rational_uminus
|
|
53
|
+
arity: 0
|
|
54
|
+
defined_at: references/ruby/rational.c:2770
|
|
55
|
+
c_body_at: references/ruby/rational.c:621
|
|
56
|
+
c_effects: []
|
|
57
|
+
purity: leaf
|
|
58
|
+
rbs:
|
|
59
|
+
- "() -> Rational"
|
|
60
|
+
rbs_at: references/rbs/core/rational.rbs:138
|
|
61
|
+
"+":
|
|
62
|
+
source: c
|
|
63
|
+
cfunc: rb_rational_plus
|
|
64
|
+
arity: 1
|
|
65
|
+
defined_at: references/ruby/rational.c:2771
|
|
66
|
+
c_body_at: references/ruby/rational.c:745
|
|
67
|
+
c_effects:
|
|
68
|
+
- coerce_fallback
|
|
69
|
+
purity: leaf_when_numeric
|
|
70
|
+
rbs:
|
|
71
|
+
- "(Float) -> Float"
|
|
72
|
+
- "(Complex) -> Complex"
|
|
73
|
+
- "(Numeric) -> Rational"
|
|
74
|
+
rbs_at: references/rbs/core/rational.rbs:109
|
|
75
|
+
"-":
|
|
76
|
+
source: c
|
|
77
|
+
cfunc: rb_rational_minus
|
|
78
|
+
arity: 1
|
|
79
|
+
defined_at: references/ruby/rational.c:2772
|
|
80
|
+
c_body_at: references/ruby/rational.c:786
|
|
81
|
+
c_effects:
|
|
82
|
+
- coerce_fallback
|
|
83
|
+
purity: leaf_when_numeric
|
|
84
|
+
rbs:
|
|
85
|
+
- "(Float) -> Float"
|
|
86
|
+
- "(Complex) -> Complex"
|
|
87
|
+
- "(Numeric) -> Rational"
|
|
88
|
+
rbs_at: references/rbs/core/rational.rbs:125
|
|
89
|
+
"*":
|
|
90
|
+
source: c
|
|
91
|
+
cfunc: rb_rational_mul
|
|
92
|
+
arity: 1
|
|
93
|
+
defined_at: references/ruby/rational.c:2773
|
|
94
|
+
c_body_at: references/ruby/rational.c:884
|
|
95
|
+
c_effects:
|
|
96
|
+
- coerce_fallback
|
|
97
|
+
purity: leaf_when_numeric
|
|
98
|
+
rbs:
|
|
99
|
+
- "(Integer) -> Rational"
|
|
100
|
+
- "(Rational) -> Rational"
|
|
101
|
+
- "[T < Numeric] (T) -> T"
|
|
102
|
+
rbs_at: references/rbs/core/rational.rbs:67
|
|
103
|
+
"/":
|
|
104
|
+
source: c
|
|
105
|
+
cfunc: rb_rational_div
|
|
106
|
+
arity: 1
|
|
107
|
+
defined_at: references/ruby/rational.c:2774
|
|
108
|
+
c_body_at: references/ruby/rational.c:925
|
|
109
|
+
c_effects:
|
|
110
|
+
- coerce_fallback
|
|
111
|
+
- raises
|
|
112
|
+
purity: leaf_when_numeric
|
|
113
|
+
rbs:
|
|
114
|
+
- "(Float) -> Float"
|
|
115
|
+
- "(Complex) -> Complex"
|
|
116
|
+
- "(Numeric) -> Rational"
|
|
117
|
+
rbs_at: references/rbs/core/rational.rbs:152
|
|
118
|
+
quo:
|
|
119
|
+
source: c
|
|
120
|
+
cfunc: rb_rational_div
|
|
121
|
+
arity: 1
|
|
122
|
+
defined_at: references/ruby/rational.c:2775
|
|
123
|
+
c_body_at: references/ruby/rational.c:925
|
|
124
|
+
c_effects:
|
|
125
|
+
- coerce_fallback
|
|
126
|
+
- raises
|
|
127
|
+
purity: leaf_when_numeric
|
|
128
|
+
rbs:
|
|
129
|
+
- "(Float) -> Float"
|
|
130
|
+
- "(Complex) -> Complex"
|
|
131
|
+
- "(Numeric) -> Rational"
|
|
132
|
+
rbs_at: references/rbs/core/rational.rbs:363
|
|
133
|
+
fdiv:
|
|
134
|
+
source: c
|
|
135
|
+
cfunc: nurat_fdiv
|
|
136
|
+
arity: 1
|
|
137
|
+
defined_at: references/ruby/rational.c:2776
|
|
138
|
+
c_body_at: references/ruby/rational.c:973
|
|
139
|
+
c_effects:
|
|
140
|
+
- dispatch
|
|
141
|
+
purity: dispatch
|
|
142
|
+
rbs:
|
|
143
|
+
- "(Numeric) -> Float"
|
|
144
|
+
rbs_at: references/rbs/core/rational.rbs:265
|
|
145
|
+
"**":
|
|
146
|
+
source: c
|
|
147
|
+
cfunc: nurat_expt
|
|
148
|
+
arity: 1
|
|
149
|
+
defined_at: references/ruby/rational.c:2777
|
|
150
|
+
c_body_at: references/ruby/rational.c:1002
|
|
151
|
+
c_effects:
|
|
152
|
+
- coerce_fallback
|
|
153
|
+
- raises
|
|
154
|
+
purity: leaf_when_numeric
|
|
155
|
+
rbs:
|
|
156
|
+
- "(Complex) -> Complex"
|
|
157
|
+
- "(Numeric) -> Numeric"
|
|
158
|
+
rbs_at: references/rbs/core/rational.rbs:84
|
|
159
|
+
"<=>":
|
|
160
|
+
source: c
|
|
161
|
+
cfunc: rb_rational_cmp
|
|
162
|
+
arity: 1
|
|
163
|
+
defined_at: references/ruby/rational.c:2779
|
|
164
|
+
c_body_at: references/ruby/rational.c:1106
|
|
165
|
+
c_effects:
|
|
166
|
+
- coerce_fallback
|
|
167
|
+
purity: leaf_when_numeric
|
|
168
|
+
rbs:
|
|
169
|
+
- "(Integer | Rational) -> Integer"
|
|
170
|
+
- "(untyped) -> Integer?"
|
|
171
|
+
rbs_at: references/rbs/core/rational.rbs:182
|
|
172
|
+
"==":
|
|
173
|
+
source: c
|
|
174
|
+
cfunc: nurat_eqeq_p
|
|
175
|
+
arity: 1
|
|
176
|
+
defined_at: references/ruby/rational.c:2780
|
|
177
|
+
c_body_at: references/ruby/rational.c:1159
|
|
178
|
+
c_effects:
|
|
179
|
+
- dispatch
|
|
180
|
+
purity: dispatch
|
|
181
|
+
rbs:
|
|
182
|
+
- "(untyped) -> bool"
|
|
183
|
+
rbs_at: references/rbs/core/rational.rbs:197
|
|
184
|
+
coerce:
|
|
185
|
+
source: c
|
|
186
|
+
cfunc: nurat_coerce
|
|
187
|
+
arity: 1
|
|
188
|
+
defined_at: references/ruby/rational.c:2781
|
|
189
|
+
c_body_at: references/ruby/rational.c:1201
|
|
190
|
+
c_effects:
|
|
191
|
+
- raises
|
|
192
|
+
purity: leaf
|
|
193
|
+
rbs:
|
|
194
|
+
- "(Numeric) -> [ Numeric, Numeric ]"
|
|
195
|
+
rbs_at: references/rbs/core/rational.rbs:237
|
|
196
|
+
positive?:
|
|
197
|
+
source: c
|
|
198
|
+
cfunc: nurat_positive_p
|
|
199
|
+
arity: 0
|
|
200
|
+
defined_at: references/ruby/rational.c:2783
|
|
201
|
+
c_body_at: references/ruby/rational.c:1238
|
|
202
|
+
c_effects: []
|
|
203
|
+
purity: leaf
|
|
204
|
+
rbs:
|
|
205
|
+
- "() -> bool"
|
|
206
|
+
rbs_at: references/rbs/core/rational.rbs:352
|
|
207
|
+
negative?:
|
|
208
|
+
source: c
|
|
209
|
+
cfunc: nurat_negative_p
|
|
210
|
+
arity: 0
|
|
211
|
+
defined_at: references/ruby/rational.c:2784
|
|
212
|
+
c_body_at: references/ruby/rational.c:1251
|
|
213
|
+
c_effects: []
|
|
214
|
+
purity: leaf
|
|
215
|
+
rbs:
|
|
216
|
+
- "() -> bool"
|
|
217
|
+
rbs_at: references/rbs/core/rational.rbs:329
|
|
218
|
+
abs:
|
|
219
|
+
source: c
|
|
220
|
+
cfunc: rb_rational_abs
|
|
221
|
+
arity: 0
|
|
222
|
+
defined_at: references/ruby/rational.c:2785
|
|
223
|
+
c_body_at: references/ruby/rational.c:1270
|
|
224
|
+
c_effects: []
|
|
225
|
+
purity: leaf
|
|
226
|
+
rbs:
|
|
227
|
+
- "() -> Rational"
|
|
228
|
+
rbs_at: references/rbs/core/rational.rbs:209
|
|
229
|
+
magnitude:
|
|
230
|
+
source: c
|
|
231
|
+
cfunc: rb_rational_abs
|
|
232
|
+
arity: 0
|
|
233
|
+
defined_at: references/ruby/rational.c:2786
|
|
234
|
+
c_body_at: references/ruby/rational.c:1270
|
|
235
|
+
c_effects: []
|
|
236
|
+
purity: leaf
|
|
237
|
+
floor:
|
|
238
|
+
source: c
|
|
239
|
+
cfunc: nurat_floor_n
|
|
240
|
+
arity: -1
|
|
241
|
+
defined_at: references/ruby/rational.c:2788
|
|
242
|
+
c_body_at: references/ruby/rational.c:1466
|
|
243
|
+
c_effects: []
|
|
244
|
+
purity: leaf
|
|
245
|
+
rbs:
|
|
246
|
+
- "() -> Integer"
|
|
247
|
+
- "(Integer digits) -> (Integer | Rational)"
|
|
248
|
+
rbs_at: references/rbs/core/rational.rbs:290
|
|
249
|
+
ceil:
|
|
250
|
+
source: c
|
|
251
|
+
cfunc: nurat_ceil_n
|
|
252
|
+
arity: -1
|
|
253
|
+
defined_at: references/ruby/rational.c:2789
|
|
254
|
+
c_body_at: references/ruby/rational.c:1496
|
|
255
|
+
c_effects: []
|
|
256
|
+
purity: leaf
|
|
257
|
+
rbs:
|
|
258
|
+
- "() -> Integer"
|
|
259
|
+
- "(Integer digits) -> (Integer | Rational)"
|
|
260
|
+
rbs_at: references/rbs/core/rational.rbs:234
|
|
261
|
+
truncate:
|
|
262
|
+
source: c
|
|
263
|
+
cfunc: nurat_truncate_n
|
|
264
|
+
arity: -1
|
|
265
|
+
defined_at: references/ruby/rational.c:2790
|
|
266
|
+
c_body_at: references/ruby/rational.c:1526
|
|
267
|
+
c_effects: []
|
|
268
|
+
purity: leaf
|
|
269
|
+
rbs:
|
|
270
|
+
- "() -> Integer"
|
|
271
|
+
- "(Integer ndigits) -> (Integer | Rational)"
|
|
272
|
+
rbs_at: references/rbs/core/rational.rbs:500
|
|
273
|
+
round:
|
|
274
|
+
source: c
|
|
275
|
+
cfunc: nurat_round_n
|
|
276
|
+
arity: -1
|
|
277
|
+
defined_at: references/ruby/rational.c:2791
|
|
278
|
+
c_body_at: references/ruby/rational.c:1569
|
|
279
|
+
c_effects: []
|
|
280
|
+
purity: leaf
|
|
281
|
+
rbs:
|
|
282
|
+
- "(?half: :up | :down | :even) -> Integer"
|
|
283
|
+
- "(Integer digits, ?half: :up | :down | :even) -> (Integer | Rational)"
|
|
284
|
+
rbs_at: references/rbs/core/rational.rbs:422
|
|
285
|
+
to_i:
|
|
286
|
+
source: c
|
|
287
|
+
cfunc: nurat_truncate
|
|
288
|
+
arity: 0
|
|
289
|
+
defined_at: references/ruby/rational.c:2793
|
|
290
|
+
c_body_at: references/ruby/rational.c:1309
|
|
291
|
+
c_effects: []
|
|
292
|
+
purity: leaf
|
|
293
|
+
rbs:
|
|
294
|
+
- "() -> Integer"
|
|
295
|
+
rbs_at: references/rbs/core/rational.rbs:452
|
|
296
|
+
to_f:
|
|
297
|
+
source: c
|
|
298
|
+
cfunc: nurat_to_f
|
|
299
|
+
arity: 0
|
|
300
|
+
defined_at: references/ruby/rational.c:2794
|
|
301
|
+
c_body_at: references/ruby/rational.c:1607
|
|
302
|
+
c_effects: []
|
|
303
|
+
purity: leaf
|
|
304
|
+
rbs:
|
|
305
|
+
- "() -> Float"
|
|
306
|
+
rbs_at: references/rbs/core/rational.rbs:436
|
|
307
|
+
to_r:
|
|
308
|
+
source: c
|
|
309
|
+
cfunc: nurat_to_r
|
|
310
|
+
arity: 0
|
|
311
|
+
defined_at: references/ruby/rational.c:2795
|
|
312
|
+
c_body_at: references/ruby/rational.c:1622
|
|
313
|
+
c_effects: []
|
|
314
|
+
purity: leaf
|
|
315
|
+
rbs:
|
|
316
|
+
- "() -> Rational"
|
|
317
|
+
rbs_at: references/rbs/core/rational.rbs:463
|
|
318
|
+
rationalize:
|
|
319
|
+
source: c
|
|
320
|
+
cfunc: nurat_rationalize
|
|
321
|
+
arity: -1
|
|
322
|
+
defined_at: references/ruby/rational.c:2796
|
|
323
|
+
c_body_at: references/ruby/rational.c:1756
|
|
324
|
+
c_effects: []
|
|
325
|
+
purity: leaf
|
|
326
|
+
rbs:
|
|
327
|
+
- "(?Numeric eps) -> Rational"
|
|
328
|
+
rbs_at: references/rbs/core/rational.rbs:380
|
|
329
|
+
hash:
|
|
330
|
+
source: c
|
|
331
|
+
cfunc: nurat_hash
|
|
332
|
+
arity: 0
|
|
333
|
+
defined_at: references/ruby/rational.c:2798
|
|
334
|
+
c_body_at: references/ruby/rational.c:1803
|
|
335
|
+
c_effects: []
|
|
336
|
+
purity: leaf
|
|
337
|
+
rbs:
|
|
338
|
+
- "() -> Integer"
|
|
339
|
+
rbs_at: references/rbs/core/rational.rbs:298
|
|
340
|
+
to_s:
|
|
341
|
+
source: c
|
|
342
|
+
cfunc: nurat_to_s
|
|
343
|
+
arity: 0
|
|
344
|
+
defined_at: references/ruby/rational.c:2800
|
|
345
|
+
c_body_at: references/ruby/rational.c:1833
|
|
346
|
+
c_effects: []
|
|
347
|
+
purity: leaf
|
|
348
|
+
rbs:
|
|
349
|
+
- "() -> String"
|
|
350
|
+
rbs_at: references/rbs/core/rational.rbs:475
|
|
351
|
+
inspect:
|
|
352
|
+
source: c
|
|
353
|
+
cfunc: nurat_inspect
|
|
354
|
+
arity: 0
|
|
355
|
+
defined_at: references/ruby/rational.c:2801
|
|
356
|
+
c_body_at: references/ruby/rational.c:1849
|
|
357
|
+
c_effects: []
|
|
358
|
+
purity: leaf
|
|
359
|
+
rbs:
|
|
360
|
+
- "() -> String"
|
|
361
|
+
rbs_at: references/rbs/core/rational.rbs:310
|
|
362
|
+
singleton_methods: {}
|
|
363
|
+
undefined:
|
|
364
|
+
- allocate
|
|
365
|
+
- new
|
|
@@ -1556,6 +1556,15 @@ classes:
|
|
|
1556
1556
|
- "(untyped object) -> String?"
|
|
1557
1557
|
rbs_at: references/rbs/core/string.rbs:980
|
|
1558
1558
|
undefined: []
|
|
1559
|
+
UnicodeNormalize:
|
|
1560
|
+
parent: Module
|
|
1561
|
+
defined_at: references/ruby/string.c:12943
|
|
1562
|
+
includes: []
|
|
1563
|
+
constants: {}
|
|
1564
|
+
aliases: {}
|
|
1565
|
+
instance_methods: {}
|
|
1566
|
+
singleton_methods: {}
|
|
1567
|
+
undefined: []
|
|
1559
1568
|
Symbol:
|
|
1560
1569
|
parent: Object
|
|
1561
1570
|
defined_at: references/ruby/string.c:12956
|
|
@@ -125,8 +125,9 @@ classes:
|
|
|
125
125
|
arity: 0
|
|
126
126
|
defined_at: references/ruby/time.c:5997
|
|
127
127
|
c_body_at: references/ruby/time.c:4196
|
|
128
|
-
c_effects:
|
|
129
|
-
|
|
128
|
+
c_effects:
|
|
129
|
+
- mutate
|
|
130
|
+
purity: mutates_self
|
|
130
131
|
rbs:
|
|
131
132
|
- "() -> Time"
|
|
132
133
|
rbs_at: references/rbs/core/time.rbs:1037
|
|
@@ -136,8 +137,9 @@ classes:
|
|
|
136
137
|
arity: 0
|
|
137
138
|
defined_at: references/ruby/time.c:5998
|
|
138
139
|
c_body_at: references/ruby/time.c:4196
|
|
139
|
-
c_effects:
|
|
140
|
-
|
|
140
|
+
c_effects:
|
|
141
|
+
- mutate
|
|
142
|
+
purity: mutates_self
|
|
141
143
|
rbs:
|
|
142
144
|
- "() -> Time"
|
|
143
145
|
rbs_at: references/rbs/core/time.rbs:1573
|
data/lib/rigor/cli.rb
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "method_catalog"
|
|
4
|
+
|
|
5
|
+
module Rigor
|
|
6
|
+
module Inference
|
|
7
|
+
module Builtins
|
|
8
|
+
# `Comparable` module catalog. Singleton — load once.
|
|
9
|
+
#
|
|
10
|
+
# `Comparable` is a Ruby module, not a class, so the
|
|
11
|
+
# catalog is NOT routed through
|
|
12
|
+
# `MethodDispatcher::ConstantFolding::CATALOG_BY_CLASS`
|
|
13
|
+
# (which dispatches on the receiver's concrete class).
|
|
14
|
+
# The data is consumed by future include-aware lookup —
|
|
15
|
+
# see `docs/CURRENT_WORK.md` for the planned slice.
|
|
16
|
+
COMPARABLE_CATALOG = MethodCatalog.new(
|
|
17
|
+
path: File.expand_path(
|
|
18
|
+
"../../../../data/builtins/ruby_core/comparable.yml",
|
|
19
|
+
__dir__
|
|
20
|
+
),
|
|
21
|
+
mutating_selectors: {
|
|
22
|
+
"Comparable" => Set[]
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "method_catalog"
|
|
4
|
+
|
|
5
|
+
module Rigor
|
|
6
|
+
module Inference
|
|
7
|
+
module Builtins
|
|
8
|
+
# `Complex` catalog. Singleton — load once, consult during
|
|
9
|
+
# dispatch.
|
|
10
|
+
#
|
|
11
|
+
# `Complex` is a fully-immutable value type in Ruby: once a
|
|
12
|
+
# complex number is constructed (via `Complex(real, imag)` or
|
|
13
|
+
# `Complex.rect` / `Complex.polar`) its `real` and `imag` slots
|
|
14
|
+
# are never rewritten. Every public instance method either
|
|
15
|
+
# returns `self` unchanged or builds a fresh `Complex` /
|
|
16
|
+
# `Numeric`. The C-body classifier already correctly flags the
|
|
17
|
+
# four `:dispatch` methods (`<=>`, `to_s`, `inspect`,
|
|
18
|
+
# `rationalize`) so there are no false-positive `:leaf`
|
|
19
|
+
# entries to override. The blocklist therefore carries only
|
|
20
|
+
# the conventional `:initialize_copy` defence-in-depth entry
|
|
21
|
+
# so a hypothetical future `Constant<Complex>` carrier cannot
|
|
22
|
+
# fold an aliasing copy through the catalog (mirrors
|
|
23
|
+
# `range_catalog.rb`, `time_catalog.rb`, `date_catalog.rb`).
|
|
24
|
+
COMPLEX_CATALOG = MethodCatalog.new(
|
|
25
|
+
path: File.expand_path(
|
|
26
|
+
"../../../../data/builtins/ruby_core/complex.yml",
|
|
27
|
+
__dir__
|
|
28
|
+
),
|
|
29
|
+
mutating_selectors: {
|
|
30
|
+
"Complex" => Set[
|
|
31
|
+
# Defence in depth: `Complex` does not currently expose
|
|
32
|
+
# a public `initialize_copy`, but blocking it keeps the
|
|
33
|
+
# convention identical to every other catalog so future
|
|
34
|
+
# CRuby additions cannot leak a copy-mutator through.
|
|
35
|
+
:initialize_copy
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# `Date` and `DateTime` live in CRuby's bundled `date` gem, which
|
|
4
|
+
# is stdlib rather than core — so the constants are not visible
|
|
5
|
+
# until `date` is required. The dispatcher's `CATALOG_BY_CLASS`
|
|
6
|
+
# table references `Date` and `DateTime` at load time, so requiring
|
|
7
|
+
# the gem here (alongside the loader file that exports the catalog)
|
|
8
|
+
# keeps the wiring self-contained: a consumer that pulls in the
|
|
9
|
+
# constant-folding rule book gets the Date constants for free.
|
|
10
|
+
require "date"
|
|
11
|
+
|
|
12
|
+
require_relative "method_catalog"
|
|
13
|
+
|
|
14
|
+
module Rigor
|
|
15
|
+
module Inference
|
|
16
|
+
module Builtins
|
|
17
|
+
# `Date` / `DateTime` catalog. Singleton — load once, consult
|
|
18
|
+
# during dispatch.
|
|
19
|
+
#
|
|
20
|
+
# `Date` and `DateTime` both come from CRuby's bundled `date`
|
|
21
|
+
# gem (`references/ruby/ext/date/date_core.c`). A single
|
|
22
|
+
# `Init_date_core` function registers them, so the catalog
|
|
23
|
+
# carries both classes — `Date` plus the `DateTime` subclass
|
|
24
|
+
# whose own Init block extends with `hour` / `min` /
|
|
25
|
+
# `strftime` / `iso8601` etc. The Ruby-side prelude
|
|
26
|
+
# (`lib/date.rb`) only contributes `Date#infinite?` and the
|
|
27
|
+
# nested `Date::Infinity` class; the bulk of the surface is
|
|
28
|
+
# in C.
|
|
29
|
+
#
|
|
30
|
+
# Date / DateTime receivers are not lifted to a `Constant`
|
|
31
|
+
# carrier today (there is no Date literal node — the closest
|
|
32
|
+
# is `Date.today` / `Date.parse(...)`, which produce
|
|
33
|
+
# `Nominal[Date]`). The catalog wiring therefore mostly
|
|
34
|
+
# governs:
|
|
35
|
+
#
|
|
36
|
+
# 1. The Integer-typed reader surface (`#year`, `#month`,
|
|
37
|
+
# `#day`, `#wday`, `#hour`, `#min`, `#sec`) — RBS-declared
|
|
38
|
+
# `Integer` is preserved through dispatch.
|
|
39
|
+
# 2. The blocklist below, which keeps mutator-style methods
|
|
40
|
+
# that the C-body classifier already flagged
|
|
41
|
+
# (`mutates_self`) from being missed by a future
|
|
42
|
+
# `Constant<Date>` carrier, plus a defensive
|
|
43
|
+
# `:initialize_copy` entry for symmetry with the other
|
|
44
|
+
# catalogs.
|
|
45
|
+
#
|
|
46
|
+
# The non-bang `#next_day` / `#prev_day` / `#next_month` /
|
|
47
|
+
# `#prev_month` / `#next_year` / `#prev_year` / `#>>` / `#<<`
|
|
48
|
+
# selectors all RETURN brand-new `Date` objects rather than
|
|
49
|
+
# mutating the receiver — they intentionally stay
|
|
50
|
+
# catalog-eligible. The two real mutators
|
|
51
|
+
# (`#initialize_copy`, `#marshal_load`) are already classified
|
|
52
|
+
# `:mutates_self` by the C-body regex, so they fall out of
|
|
53
|
+
# `MethodCatalog#safe_for_folding?` without an explicit
|
|
54
|
+
# blocklist entry; the entries below are defense-in-depth
|
|
55
|
+
# against indirect mutators the regex might miss in a future
|
|
56
|
+
# CRuby bump.
|
|
57
|
+
DATE_CATALOG = MethodCatalog.new(
|
|
58
|
+
path: File.expand_path(
|
|
59
|
+
"../../../../data/builtins/ruby_core/date.yml",
|
|
60
|
+
__dir__
|
|
61
|
+
),
|
|
62
|
+
mutating_selectors: {
|
|
63
|
+
"Date" => Set[
|
|
64
|
+
# `d_lite_initialize_copy` is already classed
|
|
65
|
+
# `:mutates_self` by the regex (it calls
|
|
66
|
+
# `rb_check_frozen` and rewrites the receiver's
|
|
67
|
+
# internal `dat` slots). Listed here for symmetry with
|
|
68
|
+
# String / Array / Range / Set / Time and to keep the
|
|
69
|
+
# blocklist self-documenting.
|
|
70
|
+
:initialize_copy,
|
|
71
|
+
# `d_lite_fill` is a `#ifndef NDEBUG` debug method that
|
|
72
|
+
# warms the receiver's cached `simple` / `complex`
|
|
73
|
+
# fields via the `get_s_*` / `get_c_*` macros. The
|
|
74
|
+
# macros perform in-place writes on the receiver's
|
|
75
|
+
# internal `dat` struct but use no helper the C-body
|
|
76
|
+
# regex recognises, so the classifier mis-flags it
|
|
77
|
+
# `:leaf`. Blocked so a future `Constant<Date>` carrier
|
|
78
|
+
# never folds it.
|
|
79
|
+
:fill
|
|
80
|
+
],
|
|
81
|
+
"DateTime" => Set[
|
|
82
|
+
# `DateTime` inherits the bulk of its surface from
|
|
83
|
+
# `Date`. The dedicated DateTime-side methods are all
|
|
84
|
+
# readers (`hour`, `min`, …) plus formatting
|
|
85
|
+
# converters (`strftime`, `iso8601`, …); none mutate
|
|
86
|
+
# the receiver. The single defensive entry mirrors the
|
|
87
|
+
# Date side so that the inherited
|
|
88
|
+
# `Date#initialize_copy` (registered against
|
|
89
|
+
# `cDateTime` through subclassing) cannot fold through
|
|
90
|
+
# the catalog if a future `Constant<DateTime>` carrier
|
|
91
|
+
# ever lands.
|
|
92
|
+
:initialize_copy
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "method_catalog"
|
|
4
|
+
|
|
5
|
+
module Rigor
|
|
6
|
+
module Inference
|
|
7
|
+
module Builtins
|
|
8
|
+
# `Enumerable` module catalog. Singleton — load once.
|
|
9
|
+
#
|
|
10
|
+
# `Enumerable` is a Ruby module, not a class, so the
|
|
11
|
+
# catalog is NOT routed through
|
|
12
|
+
# `MethodDispatcher::ConstantFolding::CATALOG_BY_CLASS`
|
|
13
|
+
# (which dispatches on the receiver's concrete class).
|
|
14
|
+
# The data is consumed by future include-aware lookup —
|
|
15
|
+
# see `docs/CURRENT_WORK.md` for the planned slice.
|
|
16
|
+
ENUMERABLE_CATALOG = MethodCatalog.new(
|
|
17
|
+
path: File.expand_path(
|
|
18
|
+
"../../../../data/builtins/ruby_core/enumerable.yml",
|
|
19
|
+
__dir__
|
|
20
|
+
),
|
|
21
|
+
mutating_selectors: {
|
|
22
|
+
"Enumerable" => Set[]
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "method_catalog"
|
|
4
|
+
|
|
5
|
+
module Rigor
|
|
6
|
+
module Inference
|
|
7
|
+
module Builtins
|
|
8
|
+
# `Rational` catalog. Singleton — load once, consult during
|
|
9
|
+
# dispatch.
|
|
10
|
+
#
|
|
11
|
+
# Rational is fully immutable: numerator / denominator slots
|
|
12
|
+
# are written once during `nurat_s_new_internal` and the C
|
|
13
|
+
# body never reaches for `rb_check_frozen`. Every catalog
|
|
14
|
+
# entry classifies cleanly (`:leaf`, `:leaf_when_numeric`,
|
|
15
|
+
# or `:dispatch` for the two methods that delegate into
|
|
16
|
+
# user-redefinable `==` / `Float()` — `nurat_eqeq_p` and
|
|
17
|
+
# `nurat_fdiv`). Bang-suffixed mutators do not exist on
|
|
18
|
+
# Rational.
|
|
19
|
+
#
|
|
20
|
+
# The blocklist therefore stays minimal. `initialize_copy`
|
|
21
|
+
# is added defensively (mirrors Range / Set) so a
|
|
22
|
+
# hypothetical future `Constant<Rational>` carrier cannot
|
|
23
|
+
# fold an aliasing copy through the catalog and surface a
|
|
24
|
+
# shared mutable handle.
|
|
25
|
+
RATIONAL_CATALOG = MethodCatalog.new(
|
|
26
|
+
path: File.expand_path(
|
|
27
|
+
"../../../../data/builtins/ruby_core/rational.yml",
|
|
28
|
+
__dir__
|
|
29
|
+
),
|
|
30
|
+
mutating_selectors: {
|
|
31
|
+
"Rational" => Set[
|
|
32
|
+
:initialize_copy
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|