katakata_irb 0.1.12 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,995 +0,0 @@
1
- require 'ripper'
2
- require 'set'
3
- require_relative 'types'
4
- require_relative 'scope'
5
-
6
- class KatakataIrb::TypeSimulator
7
- class DigTarget
8
- def initialize(parents, receiver, &block)
9
- @dig_ids = parents.to_h { [_1.__id__, true] }
10
- @target_id = receiver.__id__
11
- @block = block
12
- end
13
-
14
- def dig?(node) = @dig_ids[node.__id__]
15
- def target?(node) = @target_id == node.__id__
16
- def resolve(type, scope)
17
- @block.call type, scope
18
- end
19
- end
20
-
21
- module LexerElemMatcher
22
- refine Ripper::Lexer::Elem do
23
- def deconstruct_keys(_keys)
24
- {
25
- tok: tok,
26
- event: event,
27
- label: state.allbits?(Ripper::EXPR_LABEL),
28
- beg: state.allbits?(Ripper::EXPR_BEG),
29
- dot: state.allbits?(Ripper::EXPR_DOT)
30
- }
31
- end
32
- end
33
- end
34
- using LexerElemMatcher
35
-
36
- OBJECT_METHODS = {
37
- to_s: KatakataIrb::Types::STRING,
38
- to_str: KatakataIrb::Types::STRING,
39
- to_a: KatakataIrb::Types::ARRAY,
40
- to_ary: KatakataIrb::Types::ARRAY,
41
- to_h: KatakataIrb::Types::HASH,
42
- to_hash: KatakataIrb::Types::HASH,
43
- to_i: KatakataIrb::Types::INTEGER,
44
- to_int: KatakataIrb::Types::INTEGER,
45
- to_f: KatakataIrb::Types::FLOAT,
46
- to_c: KatakataIrb::Types::COMPLEX,
47
- to_r: KatakataIrb::Types::RATIONAL
48
- }
49
-
50
- def initialize(dig_targets)
51
- @dig_targets = dig_targets
52
- end
53
-
54
- def simulate_evaluate(sexp, scope, case_target: nil)
55
- result = simulate_evaluate_inner(sexp, scope, case_target: case_target)
56
- @dig_targets.resolve result, scope if @dig_targets.target?(sexp)
57
- result
58
- end
59
-
60
- def simulate_evaluate_inner(sexp, scope, case_target: nil)
61
- case sexp
62
- in [:program, statements]
63
- statements.map { simulate_evaluate _1, scope }.last
64
- in [:def | :defs,]
65
- sexp in [:def, _method_name_exp, params, body_stmt]
66
- sexp in [:defs, receiver_exp, _dot_exp, _method_name_exp, params, body_stmt]
67
- if receiver_exp
68
- receiver_exp in [:paren, receiver_exp]
69
- self_type = simulate_evaluate receiver_exp, scope
70
- else
71
- current_self_types = scope.self_type.types
72
- self_types = current_self_types.map do |type|
73
- if type.is_a?(KatakataIrb::Types::SingletonType) && type.module_or_class.is_a?(Class)
74
- KatakataIrb::Types::InstanceType.new type.module_or_class
75
- else
76
- type
77
- end
78
- end
79
- self_type = KatakataIrb::Types::UnionType[*self_types]
80
- end
81
- if @dig_targets.dig? sexp
82
- params in [:paren, params]
83
- params ||= [:params, nil, nil, nil, nil, nil, nil, nil] # params might be nil in ruby 3.0
84
- params_table = extract_param_names(params).to_h { [_1, KatakataIrb::Types::NIL] }
85
- method_scope = KatakataIrb::Scope.new(
86
- scope,
87
- { **params_table, KatakataIrb::Scope::SELF => self_type, KatakataIrb::Scope::BREAK_RESULT => nil, KatakataIrb::Scope::NEXT_RESULT => nil, KatakataIrb::Scope::RETURN_RESULT => nil },
88
- trace_lvar: false
89
- )
90
- evaluate_assign_params params, [], method_scope
91
- method_scope.conditional { evaluate_param_defaults params, _1 }
92
- simulate_evaluate body_stmt, method_scope
93
- method_scope.merge_jumps
94
- scope.update method_scope
95
- end
96
- KatakataIrb::Types::SYMBOL
97
- in [:@int,]
98
- KatakataIrb::Types::INTEGER
99
- in [:@float,]
100
- KatakataIrb::Types::FLOAT
101
- in [:@rational,]
102
- KatakataIrb::Types::RATIONAL
103
- in [:@imaginary,]
104
- KatakataIrb::Types::COMPLEX
105
- in [:@tstring_content,]
106
- KatakataIrb::Types::STRING
107
- in [:symbol_literal,]
108
- KatakataIrb::Types::SYMBOL
109
- in [:dyna_symbol, [:string_content, *statements]]
110
- statements.each { simulate_evaluate _1, scope }
111
- KatakataIrb::Types::SYMBOL
112
- in [:@CHAR,]
113
- KatakataIrb::Types::STRING
114
- in [:@backref,]
115
- KatakataIrb::Types::UnionType[KatakataIrb::Types::STRING, KatakataIrb::Types::NIL]
116
- in [:string_literal, [:string_content, *statements]]
117
- statements.each { simulate_evaluate _1, scope }
118
- KatakataIrb::Types::STRING
119
- in [:xstring_literal, statements]
120
- statements.each { simulate_evaluate _1, scope }
121
- KatakataIrb::Types::STRING
122
- in [:string_embexpr, statements]
123
- statements.each { simulate_evaluate _1, scope }
124
- KatakataIrb::Types::STRING
125
- in [:string_dvar,]
126
- KatakataIrb::Types::STRING
127
- in [:regexp_literal, statements, _regexp_end]
128
- statements.each { simulate_evaluate _1, scope }
129
- KatakataIrb::Types::REGEXP
130
- in [:array, [:args_add_star,] => star]
131
- args, kwargs = retrieve_method_args star
132
- types = args.flat_map do |elem|
133
- if elem.is_a? KatakataIrb::Types::Splat
134
- splat = simulate_evaluate elem.item, scope
135
- array_elem, non_array = partition_to_array splat.nonnillable, :to_a
136
- KatakataIrb::Types::UnionType[*array_elem, *non_array]
137
- else
138
- simulate_evaluate elem, scope
139
- end
140
- end
141
- types << kwargs_type(kwargs, scope) if kwargs && kwargs.any?
142
- KatakataIrb::Types::InstanceType.new Array, Elem: KatakataIrb::Types::UnionType[*types]
143
- in [:array, statements]
144
- if statements.nil? || statements.empty?
145
- KatakataIrb::Types::ARRAY
146
- elsif statements.all? { _1 in [Symbol,] }
147
- # normal array
148
- elem = statements ? KatakataIrb::Types::UnionType[*statements.map { simulate_evaluate _1, scope }] : KatakataIrb::Types::NIL
149
- KatakataIrb::Types::InstanceType.new Array, Elem: elem
150
- else
151
- # %I[] or %W[]
152
- statements.each do |sub_statements|
153
- sub_statements.each { simulate_evaluate _1, scope }
154
- end
155
- # TODO: use AST because Ripper.sexp('%I[a]') == Ripper.sexp('%W[a]')
156
- elem = KatakataIrb::Types::UnionType[KatakataIrb::Types::STRING, KatakataIrb::Types::SYMBOL]
157
- KatakataIrb::Types::InstanceType.new Array, Elem: elem
158
- end
159
- in [:bare_assoc_hash, args]
160
- simulate_evaluate [:hash, [:assoclist_from_args, args]], scope
161
- in [:hash, [:assoclist_from_args, args]]
162
- keys = []
163
- values = []
164
- args.each do |arg|
165
- case arg
166
- in [:assoc_new, key, value]
167
- if key in [:@label, label, pos]
168
- keys << KatakataIrb::Types::SYMBOL
169
- name = label.delete ':'
170
- value ||= [:__var_ref_or_call, [name =~ /\A[A-Z]/ ? :@const : :@ident, name, pos]]
171
- else
172
- keys << simulate_evaluate(key, scope)
173
- end
174
- values << simulate_evaluate(value, scope)
175
- in [:assoc_splat, value]
176
- hash = simulate_evaluate value, scope
177
- unless hash.is_a?(KatakataIrb::Types::InstanceType) && hash.klass == Hash
178
- hash = simulate_call hash, :to_hash, [], nil, nil
179
- end
180
- if hash.is_a?(KatakataIrb::Types::InstanceType) && hash.klass == Hash
181
- keys << hash.params[:K] if hash.params[:K]
182
- values << hash.params[:V] if hash.params[:V]
183
- end
184
- end
185
- end
186
- KatakataIrb::Types::InstanceType.new Hash, K: KatakataIrb::Types::UnionType[*keys], V: KatakataIrb::Types::UnionType[*values]
187
- in [:hash, nil]
188
- KatakataIrb::Types::InstanceType.new Hash
189
- in [:paren, [Symbol,] | false => statement]
190
- # workaround for `p ()` and `p (foo)`
191
- simulate_evaluate statement, scope if statement
192
- in [:paren | :ensure | :else, statements]
193
- statements.map { simulate_evaluate _1, scope }.last
194
- in [:const_path_ref, receiver, [:@const, name,]]
195
- r = simulate_evaluate receiver, scope
196
- r.is_a?(KatakataIrb::Types::SingletonType) ? KatakataIrb::BaseScope.type_of { r.module_or_class.const_get name } : KatakataIrb::Types::NIL
197
- in [:__var_ref_or_call, [type, name, pos]]
198
- sexp = scope.has?(name) ? [:var_ref, [type, name, pos]] : [:vcall, [:@ident, name, pos]]
199
- simulate_evaluate sexp, scope
200
- in [:var_ref, [:@kw, name,]]
201
- case name
202
- in 'self'
203
- scope.self_type
204
- in 'true'
205
- KatakataIrb::Types::TRUE
206
- in 'false'
207
- KatakataIrb::Types::FALSE
208
- in 'nil'
209
- KatakataIrb::Types::NIL
210
- in '__FILE__'
211
- KatakataIrb::Types::STRING
212
- in '__LINE__'
213
- KatakataIrb::Types::INTEGER
214
- in '__ENCODING__'
215
- KatakataIrb::Types::InstanceType.new Encoding
216
- end
217
- in [:var_ref, [:@const | :@ivar | :@cvar | :@gvar | :@ident, name,]]
218
- scope[name] || KatakataIrb::Types::NIL
219
- in [:const_ref, [:@const, name,]]
220
- scope[name] || KatakataIrb::Types::NIL
221
- in [:aref, receiver, args]
222
- receiver_type = simulate_evaluate receiver, scope if receiver
223
- args, kwargs, _block = retrieve_method_args args
224
- args_type = args.map do |arg|
225
- if arg.is_a? KatakataIrb::Types::Splat
226
- simulate_evaluate arg.item, scope
227
- nil # TODO: splat
228
- else
229
- simulate_evaluate arg, scope
230
- end
231
- end
232
- simulate_call receiver_type, :[], args_type, kwargs_type(kwargs, scope), nil
233
- in [:call | :vcall | :command | :command_call | :method_add_arg | :method_add_block,]
234
- if (sexp in [:vcall, [:@ident, name,]]) && scope.has?(name)
235
- # workaround for https://bugs.ruby-lang.org/issues/19175
236
- return scope[name]
237
- end
238
- receiver, method, args, kwargs, block, optional_chain = retrieve_method_call sexp
239
- if receiver.nil? && method == 'raise'
240
- scope.terminate_with KatakataIrb::Scope::RAISE_BREAK, KatakataIrb::Types::TRUE
241
- return KatakataIrb::Types::NIL
242
- end
243
- receiver_type = receiver ? simulate_evaluate(receiver, scope) : scope.self_type
244
- evaluate_method = lambda do |scope|
245
- args_type = args.map do |arg|
246
- if arg.is_a? KatakataIrb::Types::Splat
247
- simulate_evaluate arg.item, scope
248
- nil # TODO: splat
249
- else
250
- simulate_evaluate arg, scope
251
- end
252
- end
253
-
254
- if block
255
- if block in [:symbol_literal, [:symbol, [:@ident, block_name,]]]
256
- call_block_proc = ->(block_args, _self_type) do
257
- block_receiver, *rest = block_args
258
- block_receiver ? simulate_call(block_receiver || KatakataIrb::Types::OBJECT, block_name, rest, nil, nil) : KatakataIrb::Types::OBJECT
259
- end
260
- elsif block in [:do_block | :brace_block => type, block_var, body]
261
- block_var in [:block_var, params,]
262
- call_block_proc = ->(block_args, block_self_type) do
263
- scope.conditional do |s|
264
- if params
265
- names = extract_param_names(params)
266
- else
267
- names = (1..max_numbered_params(body)).map { "_#{_1}" }
268
- params = [:params, names.map { [:@ident, _1, [0, 0]] }, nil, nil, nil, nil, nil, nil]
269
- end
270
- params_table = names.zip(block_args).to_h { [_1, _2 || KatakataIrb::Types::NIL] }
271
- table = { **params_table, KatakataIrb::Scope::BREAK_RESULT => nil, KatakataIrb::Scope::NEXT_RESULT => nil }
272
- table[KatakataIrb::Scope::SELF] = block_self_type if block_self_type
273
- block_scope = KatakataIrb::Scope.new s, table
274
- evaluate_assign_params params, block_args, block_scope
275
- block_scope.conditional { evaluate_param_defaults params, _1 } if params
276
- if type == :do_block
277
- result = simulate_evaluate body, block_scope
278
- else
279
- result = body.map { simulate_evaluate _1, block_scope }.last
280
- end
281
- block_scope.merge_jumps
282
- s.update block_scope
283
- nexts = block_scope[KatakataIrb::Scope::NEXT_RESULT]
284
- breaks = block_scope[KatakataIrb::Scope::BREAK_RESULT]
285
- if block_scope.terminated?
286
- [KatakataIrb::Types::UnionType[*nexts], breaks]
287
- else
288
- [KatakataIrb::Types::UnionType[result, *nexts], breaks]
289
- end
290
- end
291
- end
292
- else
293
- call_block_proc = ->(_block_args, _self_type) { KatakataIrb::Types::OBJECT }
294
- simulate_evaluate block, scope
295
- end
296
- end
297
- simulate_call receiver_type, method, args_type, kwargs_type(kwargs, scope), call_block_proc
298
- end
299
- if optional_chain
300
- result = scope.conditional { evaluate_method.call _1 }
301
- if receiver_type.nillable?
302
- KatakataIrb::Types::UnionType[result, KatakataIrb::Types::NIL]
303
- else
304
- result
305
- end
306
- else
307
- evaluate_method.call scope
308
- end
309
- in [:binary, a, Symbol => op, b]
310
- atype = simulate_evaluate a, scope
311
- case op
312
- when :'&&', :and
313
- btype = scope.conditional { simulate_evaluate b, _1 }
314
- KatakataIrb::Types::UnionType[btype, KatakataIrb::Types::NIL, KatakataIrb::Types::FALSE]
315
- when :'||', :or
316
- btype = scope.conditional { simulate_evaluate b, _1 }
317
- KatakataIrb::Types::UnionType[atype, btype]
318
- else
319
- btype = simulate_evaluate b, scope
320
- simulate_call atype, op, [btype], nil, nil
321
- end
322
- in [:unary, op, receiver]
323
- simulate_call simulate_evaluate(receiver, scope), op, [], nil, nil
324
- in [:lambda, params, statements]
325
- params in [:paren, params] # ->{}, -> do end
326
- statements in [:bodystmt, statements, _unknown, _unknown, _unknown] # -> do end
327
- params in [:paren, params]
328
- params_table = extract_param_names(params).to_h { [_1, KatakataIrb::Types::NIL] }
329
- block_scope = KatakataIrb::Scope.new scope, { **params_table, KatakataIrb::Scope::BREAK_RESULT => nil, KatakataIrb::Scope::NEXT_RESULT => nil, KatakataIrb::Scope::RETURN_RESULT => nil }
330
- block_scope.conditional do |s|
331
- evaluate_assign_params params, [], s
332
- s.conditional { evaluate_param_defaults params, _1 }
333
- statements.each { simulate_evaluate _1, s }
334
- end
335
- block_scope.merge_jumps
336
- scope.update block_scope
337
- KatakataIrb::Types::ProcType.new
338
- in [:assign, [:var_field, [:@gvar | :@ivar | :@cvar | :@ident | :@const, name,]], value]
339
- res = simulate_evaluate value, scope
340
- scope[name] = res
341
- res
342
- in [:assign, [:aref_field, receiver, key], value]
343
- simulate_evaluate receiver, scope
344
- args, kwargs, _block = retrieve_method_args key
345
- args.each do |arg|
346
- item = arg.is_a?(KatakataIrb::Types::Splat) ? arg.item : arg
347
- simulate_evaluate item, scope
348
- end
349
- kwargs_type kwargs, scope
350
- simulate_evaluate value, scope
351
- in [:assign, [:field, receiver, period, [:@ident,]], value]
352
- simulate_evaluate receiver, scope
353
- if period in [:@op, '&.',]
354
- scope.conditional { simulate_evaluate value, scope }
355
- else
356
- simulate_evaluate value, scope
357
- end
358
- in [:opassign, target, [:@op, op,], value]
359
- op = op.to_s.delete('=').to_sym
360
- if target in [:var_field, *field]
361
- receiver = [:var_ref, *field]
362
- elsif target in [:field, *field]
363
- receiver = [:call, *field]
364
- elsif target in [:aref_field, *field]
365
- receiver = [:aref, *field]
366
- else
367
- receiver = target
368
- end
369
- simulate_evaluate [:assign, target, [:binary, receiver, op, value]], scope
370
- in [:assign, target, value]
371
- simulate_evaluate target, scope
372
- simulate_evaluate value, scope
373
- in [:massign, targets, value]
374
- targets in [:mlhs, *targets] # (a,b) = value
375
- rhs = simulate_evaluate value, scope
376
- evaluate_massign targets, rhs, scope
377
- rhs
378
- in [:mrhs_new_from_args | :mrhs_add_star,]
379
- values, = evaluate_mrhs sexp, scope
380
- KatakataIrb::Types::InstanceType.new Array, Elem: KatakataIrb::Types::UnionType[*values]
381
- in [:ifop, cond, tval, fval]
382
- simulate_evaluate cond, scope
383
- KatakataIrb::Types::UnionType[*scope.run_branches(
384
- -> { simulate_evaluate tval, _1 },
385
- -> { simulate_evaluate fval, _1 }
386
- )]
387
- in [:if_mod | :unless_mod, cond, statement]
388
- simulate_evaluate cond, scope
389
- KatakataIrb::Types::UnionType[scope.conditional { simulate_evaluate statement, _1 }, KatakataIrb::Types::NIL]
390
- in [:if | :unless | :elsif, cond, statements, else_statement]
391
- simulate_evaluate cond, scope
392
- results = scope.run_branches(
393
- ->(s) { statements.map { simulate_evaluate _1, s }.last },
394
- ->(s) { else_statement ? simulate_evaluate(else_statement, s) : KatakataIrb::Types::NIL }
395
- )
396
- results.empty? ? KatakataIrb::Types::NIL : KatakataIrb::Types::UnionType[*results]
397
- in [:while | :until, cond, statements]
398
- inner_scope = KatakataIrb::Scope.new scope, { KatakataIrb::Scope::BREAK_RESULT => nil }, passthrough: true
399
- simulate_evaluate cond, inner_scope
400
- inner_scope.conditional { |s| statements.each { simulate_evaluate _1, s } }
401
- inner_scope.merge_jumps
402
- scope.update inner_scope
403
- breaks = inner_scope[KatakataIrb::Scope::BREAK_RESULT]
404
- breaks ? KatakataIrb::Types::UnionType[breaks, KatakataIrb::Types::NIL] : KatakataIrb::Types::NIL
405
- in [:while_mod | :until_mod, cond, statement]
406
- inner_scope = KatakataIrb::Scope.new scope, { KatakataIrb::Scope::BREAK_RESULT => nil }, passthrough: true
407
- simulate_evaluate cond, inner_scope
408
- inner_scope.conditional { |s| simulate_evaluate statement, s }
409
- inner_scope.merge_jumps
410
- scope.update inner_scope
411
- breaks = inner_scope[KatakataIrb::Scope::BREAK_RESULT]
412
- breaks ? KatakataIrb::Types::UnionType[breaks, KatakataIrb::Types::NIL] : KatakataIrb::Types::NIL
413
- in [:break | :next | :return => jump_type, value]
414
- internal_key = jump_type == :break ? KatakataIrb::Scope::BREAK_RESULT : jump_type == :next ? KatakataIrb::Scope::NEXT_RESULT : KatakataIrb::Scope::RETURN_RESULT
415
- if value.empty?
416
- jump_value = KatakataIrb::Types::NIL
417
- else
418
- values, kw = evaluate_mrhs value, scope
419
- values << kw if kw
420
- jump_value = values.size == 1 ? values.first : KatakataIrb::Types::InstanceType.new(Array, Elem: KatakataIrb::Types::UnionType[*values])
421
- end
422
- scope.terminate_with internal_key, jump_value
423
- KatakataIrb::Types::NIL
424
- in [:return0]
425
- scope.terminate_with KatakataIrb::Scope::RETURN_RESULT, KatakataIrb::Types::NIL
426
- KatakataIrb::Types::NIL
427
- in [:yield, args]
428
- evaluate_mrhs args, scope
429
- KatakataIrb::Types::OBJECT
430
- in [:yield0]
431
- KatakataIrb::Types::OBJECT
432
- in [:redo | :retry]
433
- scope.terminate
434
- in [:zsuper]
435
- KatakataIrb::Types::OBJECT
436
- in [:super, args]
437
- args, kwargs, _block = retrieve_method_args args
438
- args.each do |arg|
439
- item = arg.is_a?(KatakataIrb::Types::Splat) ? arg.item : arg
440
- simulate_evaluate item, scope
441
- end
442
- kwargs_type kwargs, scope
443
- KatakataIrb::Types::OBJECT
444
- in [:begin, body_stmt]
445
- simulate_evaluate body_stmt, scope
446
- in [:bodystmt, statements, rescue_stmt, _unknown, ensure_stmt]
447
- statements = [statements] if statements in [Symbol,] # oneliner-def body
448
- rescue_scope = KatakataIrb::Scope.new scope, { KatakataIrb::Scope::RAISE_BREAK => nil }, passthrough: true if rescue_stmt
449
- return_type = statements.map { simulate_evaluate _1, rescue_scope || scope }.last
450
- if rescue_stmt
451
- rescue_scope.merge_jumps
452
- scope.update rescue_scope
453
- return_type = KatakataIrb::Types::UnionType[return_type, scope.conditional { simulate_evaluate rescue_stmt, _1 }]
454
- end
455
- simulate_evaluate ensure_stmt, scope if ensure_stmt
456
- return_type
457
- in [:rescue, error_class_stmts, error_var_stmt, statements, rescue_stmt]
458
- return_type = scope.conditional do |s|
459
- if error_var_stmt in [:var_field, [:@ident, error_var,]]
460
- if (error_class_stmts in [:mrhs_new_from_args, Array => stmts, stmt])
461
- error_class_stmts = [*stmts, stmt]
462
- end
463
- error_classes = (error_class_stmts || []).flat_map { simulate_evaluate _1, s }.uniq
464
- error_types = error_classes.filter_map { KatakataIrb::Types::InstanceType.new _1.module_or_class if _1.is_a?(KatakataIrb::Types::SingletonType) }
465
- error_types << KatakataIrb::Types::InstanceType.new(StandardError) if error_types.empty?
466
- s[error_var] = KatakataIrb::Types::UnionType[*error_types]
467
- end
468
- statements.map { simulate_evaluate _1, s }.last
469
- end
470
- if rescue_stmt
471
- return_type = KatakataIrb::Types::UnionType[return_type, scope.conditional { simulate_evaluate rescue_stmt, _1 }]
472
- end
473
- return_type
474
- in [:rescue_mod, statement1, statement2]
475
- rescue_scope = KatakataIrb::Scope.new scope, { KatakataIrb::Scope::RAISE_BREAK => nil }, passthrough: true
476
- a = simulate_evaluate statement1, rescue_scope
477
- rescue_scope.merge_jumps
478
- scope.update rescue_scope
479
- b = scope.conditional { simulate_evaluate statement2, _1 }
480
- KatakataIrb::Types::UnionType[a, b]
481
- in [:module, module_stmt, body_stmt]
482
- module_types = simulate_evaluate(module_stmt, scope).types.grep(KatakataIrb::Types::SingletonType)
483
- module_types << KatakataIrb::Types::MODULE if module_types.empty?
484
- module_scope = KatakataIrb::Scope.new(scope, { KatakataIrb::Scope::SELF => KatakataIrb::Types::UnionType[*module_types], KatakataIrb::Scope::BREAK_RESULT => nil, KatakataIrb::Scope::NEXT_RESULT => nil, KatakataIrb::Scope::RETURN_RESULT => nil }, trace_cvar: false, trace_ivar: false, trace_lvar: false)
485
- result = simulate_evaluate body_stmt, module_scope
486
- scope.update module_scope
487
- result
488
- in [:sclass, klass_stmt, body_stmt]
489
- klass_types = simulate_evaluate(klass_stmt, scope).types.filter_map do |type|
490
- KatakataIrb::Types::SingletonType.new type.klass if type.is_a? KatakataIrb::Types::InstanceType
491
- end
492
- klass_types = [KatakataIrb::Types::CLASS] if klass_types.empty?
493
- sclass_scope = KatakataIrb::Scope.new(scope, { KatakataIrb::Scope::SELF => KatakataIrb::Types::UnionType[*klass_types], KatakataIrb::Scope::BREAK_RESULT => nil, KatakataIrb::Scope::NEXT_RESULT => nil, KatakataIrb::Scope::RETURN_RESULT => nil }, trace_cvar: false, trace_ivar: false, trace_lvar: false)
494
- result = simulate_evaluate body_stmt, sclass_scope
495
- scope.update sclass_scope
496
- result
497
- in [:class, klass_stmt, superclass_stmt, body_stmt]
498
- klass_types = simulate_evaluate(klass_stmt, scope).types
499
- klass_types += simulate_evaluate(superclass_stmt, scope).types if superclass_stmt
500
- klass_types = klass_types.select do |type|
501
- type.is_a?(KatakataIrb::Types::SingletonType) && type.module_or_class.is_a?(Class)
502
- end
503
- klass_types << KatakataIrb::Types::CLASS if klass_types.empty?
504
- klass_scope = KatakataIrb::Scope.new(scope, { KatakataIrb::Scope::SELF => KatakataIrb::Types::UnionType[*klass_types], KatakataIrb::Scope::BREAK_RESULT => nil, KatakataIrb::Scope::NEXT_RESULT => nil, KatakataIrb::Scope::RETURN_RESULT => nil }, trace_cvar: false, trace_ivar: false, trace_lvar: false)
505
- result = simulate_evaluate body_stmt, klass_scope
506
- scope.update klass_scope
507
- result
508
- in [:for, fields, enum, statements]
509
- fields = [fields] if fields in [:var_field | :field | :aref_field,]
510
- params = [:params, fields, nil, nil, nil, nil, nil, nil]
511
- enum = simulate_evaluate enum, scope
512
- extract_param_names(params).each { scope[_1] = KatakataIrb::Types::NIL }
513
- response = simulate_call enum, :first, [], nil, nil
514
- evaluate_assign_params params, [response], scope
515
- inner_scope = KatakataIrb::Scope.new scope, { KatakataIrb::Scope::BREAK_RESULT => nil }, passthrough: true
516
- scope.conditional do |s|
517
- statements.each { simulate_evaluate _1, s }
518
- end
519
- inner_scope.merge_jumps
520
- scope.update inner_scope
521
- breaks = inner_scope[KatakataIrb::Scope::BREAK_RESULT]
522
- breaks ? KatakataIrb::Types::UnionType[breaks, enum] : enum
523
- in [:when, pattern, if_statements, else_statement]
524
- eval_pattern = lambda do |s, pattern, *rest|
525
- simulate_evaluate pattern, s
526
- scope.conditional { eval_pattern.call(_1, *rest) } if rest.any?
527
- end
528
- if_branch = lambda do |s|
529
- eval_pattern.call(s, *pattern)
530
- if_statements.map { simulate_evaluate _1, s }.last
531
- end
532
- else_branch = lambda do |s|
533
- pattern.each { simulate_evaluate _1, s }
534
- simulate_evaluate(else_statement, s, case_target: case_target)
535
- end
536
- if if_statements && else_statement
537
- KatakataIrb::Types::UnionType[*scope.run_branches(if_branch, else_branch)]
538
- else
539
- KatakataIrb::Types::UnionType[scope.conditional { (if_branch || else_branch).call _1 }, KatakataIrb::Types::NIL]
540
- end
541
- in [:in, [:var_field, [:@ident, name,]], if_statements, else_statement]
542
- scope.never { simulate_evaluate else_statement, scope } if else_statement
543
- scope[name] = case_target || KatakataIrb::Types::OBJECT
544
- if_statements ? if_statements.map { simulate_evaluate _1, scope }.last : KatakataIrb::Types::NIL
545
- in [:in, pattern, if_statements, else_statement]
546
- pattern_scope = KatakataIrb::Scope.new(scope, { KatakataIrb::Scope::PATTERNMATCH_BREAK => nil }, passthrough: true)
547
- results = pattern_scope.run_branches(
548
- ->(s) {
549
- match_pattern case_target, pattern, s
550
- if_statements ? if_statements.map { simulate_evaluate _1, s }.last : KatakataIrb::Types::NIL
551
- },
552
- ->(s) {
553
- else_statement ? simulate_evaluate(else_statement, s, case_target: case_target) : KatakataIrb::Types::NIL
554
- }
555
- )
556
- pattern_scope.merge_jumps
557
- scope.update pattern_scope
558
- KatakataIrb::Types::UnionType[*results]
559
- in [:case, target_exp, match_exp]
560
- target = target_exp ? simulate_evaluate(target_exp, scope) : KatakataIrb::Types::NIL
561
- simulate_evaluate match_exp, scope, case_target: target
562
- in [:void_stmt]
563
- KatakataIrb::Types::NIL
564
- in [:dot2 | :dot3, range_beg, range_end]
565
- beg_type = simulate_evaluate range_beg, scope if range_beg
566
- end_type = simulate_evaluate range_end, scope if range_end
567
- elem = (KatakataIrb::Types::UnionType[*[beg_type, end_type].compact]).nonnillable
568
- KatakataIrb::Types::InstanceType.new Range, { Elem: elem }
569
- in [:top_const_ref, [:@const, name,]]
570
- KatakataIrb::BaseScope.type_of { Object.const_get name }
571
- in [:string_concat, a, b]
572
- simulate_evaluate a, scope
573
- simulate_evaluate b, scope
574
- KatakataIrb::Types::STRING
575
- in [:defined, expression]
576
- scope.conditional { simulate_evaluate expression, _1 }
577
- KatakataIrb::Types::UnionType[KatakataIrb::Types::STRING, KatakataIrb::Types::NIL]
578
- else
579
- KatakataIrb.log_puts
580
- KatakataIrb.log_puts :NOMATCH
581
- KatakataIrb.log_puts sexp.inspect
582
- KatakataIrb::Types::NIL
583
- end
584
- end
585
-
586
- def match_pattern(target, pattern, scope)
587
- breakable = -> { scope.terminate_with KatakataIrb::Scope::PATTERNMATCH_BREAK, KatakataIrb::Types::NIL }
588
- types = target.types
589
- case pattern
590
- in [:var_field, [:@ident, name,]]
591
- scope[name] = target
592
- in [:var_ref,] # in Array, in ^a, in nil
593
- in [:@int | :@float | :@rational | :@imaginary | :@CHAR | :symbol_literal | :string_literal | :regexp_literal,]
594
- in [:begin, statement] # in (statement)
595
- simulate_evaluate statement, scope
596
- breakable.call
597
- in [:binary, lpattern, :|, rpattern]
598
- match_pattern target, lpattern, scope
599
- scope.conditional { match_pattern target, rpattern, _1 }
600
- breakable.call
601
- in [:binary, lpattern, :'=>', [:var_field, [:@ident, name,]] => rpattern]
602
- if lpattern in [:var_ref, [:@const, _const_name,]]
603
- const_value = simulate_evaluate lpattern, scope
604
- if const_value.is_a?(KatakataIrb::Types::SingletonType) && const_value.module_or_class.is_a?(Class)
605
- scope[name] = KatakataIrb::Types::InstanceType.new const_value.module_or_class
606
- else
607
- scope[name] = KatakataIrb::Types::OBJECT
608
- end
609
- breakable.call
610
- else
611
- match_pattern target, lpattern, scope
612
- match_pattern target, rpattern, scope
613
- end
614
- in [:aryptn, _unknown, items, splat, post_items]
615
- # TODO: deconstruct keys
616
- array_types = types.select { _1.is_a?(KatakataIrb::Types::InstanceType) && _1.klass == Array }
617
- elem = KatakataIrb::Types::UnionType[*array_types.filter_map { _1.params[:Elem] }]
618
- items&.each do |item|
619
- match_pattern elem, item, scope
620
- end
621
- if splat in [:var_field, [:@ident, name,]]
622
- scope[name] = KatakataIrb::Types::InstanceType.new Array, Elem: elem
623
- breakable.call
624
- end
625
- post_items&.each do |item|
626
- match_pattern elem, item, scope
627
- end
628
- in [:hshptn, _unknown, items, splat]
629
- # TODO: deconstruct keys
630
- hash_types = types.select { _1.is_a?(KatakataIrb::Types::InstanceType) && _1.klass == Hash }
631
- key_type = KatakataIrb::Types::UnionType[*hash_types.filter_map { _1.params[:K] }]
632
- value_type = KatakataIrb::Types::UnionType[*hash_types.filter_map { _1.params[:V] }]
633
- items&.each do |key_pattern, value_pattern|
634
- if (key_pattern in [:@label, label,]) && !value_pattern
635
- name = label.delete ':'
636
- scope[name] = value_type
637
- breakable.call
638
- end
639
- match_pattern value_type, value_pattern, scope if value_pattern
640
- end
641
- if splat in [:var_field, [:@ident, name,]]
642
- scope[name] = KatakataIrb::Types::InstanceType.new Hash, K: key_type, V: value_type
643
- breakable.call
644
- end
645
- in [:if_mod, cond, ifpattern]
646
- match_pattern target, ifpattern, scope
647
- simulate_evaluate cond, scope
648
- breakable.call
649
- in [:dyna_symbol,]
650
- in [:const_path_ref,]
651
- else
652
- KatakataIrb.log_puts "Unimplemented match pattern: #{pattern}"
653
- end
654
- end
655
-
656
- def evaluate_mrhs(sexp, scope)
657
- args, kwargs, = retrieve_method_args sexp
658
- values = args.filter_map do |t|
659
- if t.is_a? KatakataIrb::Types::Splat
660
- simulate_evaluate t.item, scope
661
- # TODO
662
- nil
663
- else
664
- simulate_evaluate t, scope
665
- end
666
- end
667
- unless kwargs.empty?
668
- kvs = kwargs.map do |t|
669
- case t
670
- in KatakataIrb::Types::Splat
671
- simulate_evaluate t.item, scope
672
- # TODO
673
- [KatakataIrb::Types::SYMBOL, KatakataIrb::Types::OBJECT]
674
- in [key, value]
675
- key_type = (key in [:@label,]) ? KatakataIrb::Types::SYMBOL : simulate_evaluate(key, scope)
676
- [key_type, simulate_evaluate(value, scope)]
677
- end
678
- end
679
- key_type = KatakataIrb::Types::UnionType[*kvs.map(&:first)]
680
- value_type = KatakataIrb::Types::UnionType[*kvs.map(&:last)]
681
- kw = KatakataIrb::Types::InstanceType.new(Hash, K: key_type, V: value_type)
682
- end
683
- [values, kw]
684
- end
685
-
686
- def sized_splat(value, method, size)
687
- array_elem, non_array = partition_to_array value, method
688
- values = [KatakataIrb::Types::UnionType[*array_elem, *non_array]]
689
- values += [array_elem] * (size - 1) if array_elem && size >= 1
690
- values
691
- end
692
-
693
- def partition_to_array(value, method)
694
- arrays, non_arrays = value.types.partition { _1.is_a?(KatakataIrb::Types::InstanceType) && _1.klass == Array }
695
- non_arrays.select! do |type|
696
- to_array_result = simulate_call type, method, [], nil, nil, name_match: false
697
- if to_array_result.is_a?(KatakataIrb::Types::InstanceType) && to_array_result.klass == Array
698
- arrays << to_array_result
699
- false
700
- else
701
- true
702
- end
703
- end
704
- array_elem = arrays.empty? ? nil : KatakataIrb::Types::UnionType[*arrays.map { _1.params[:Elem] || KatakataIrb::Types::OBJECT }]
705
- non_array = non_arrays.empty? ? nil : KatakataIrb::Types::UnionType[*non_arrays]
706
- [array_elem, non_array]
707
- end
708
-
709
- def evaluate_massign(sexp, values, scope)
710
- values = sized_splat values, :to_ary, sexp.size unless values.is_a? Array
711
- rest_index = sexp.find_index { _1 in [:rest_param, ]}
712
- if rest_index
713
- pre = rest_index ? sexp[0...rest_index] : sexp
714
- post = rest_index ? sexp[rest_index + 1..] : []
715
- sexp[rest_index] in [:rest_param, rest_field]
716
- rest_values = values[pre.size...values.size - post.size] || []
717
- rest_type = KatakataIrb::Types::InstanceType.new Array, Elem: KatakataIrb::Types::UnionType[*rest_values]
718
- pairs = pre.zip(values.first(pre.size)) + [[rest_field, rest_type]] + post.zip(values.last(post.size))
719
- else
720
- pairs = sexp.zip values
721
- end
722
- pairs.each do |field, value|
723
- case field
724
- in [:@ident, name,]
725
- # block arg mlhs
726
- scope[name] = value || KatakataIrb::Types::OBJECT
727
- in [:var_field, [:@gvar | :@ivar | :@cvar | :@ident | :@const, name,]]
728
- # massign
729
- scope[name] = value || KatakataIrb::Types::OBJECT
730
- in [:mlhs, *mlhs]
731
- evaluate_massign mlhs, value || [], scope
732
- in [:field, receiver,]
733
- # (a=x).b, c = value
734
- simulate_evaluate receiver, scope
735
- in [:aref_field, *field]
736
- # (a=x)[i=y, j=z], b = value
737
- simulate_evaluate [:aref, *field], scope
738
- in nil
739
- # a, *, b = value
740
- end
741
- end
742
- end
743
-
744
- def kwargs_type(kwargs, scope)
745
- return if kwargs.empty?
746
- keys = []
747
- values = []
748
- kwargs.each do |kv|
749
- if kv.is_a? KatakataIrb::Types::Splat
750
- hash = simulate_evaluate kv.item, scope
751
- unless hash.is_a?(KatakataIrb::Types::InstanceType) && hash.klass == Hash
752
- hash = simulate_call hash, :to_hash, [], nil, nil
753
- end
754
- if hash.is_a?(KatakataIrb::Types::InstanceType) && hash.klass == Hash
755
- keys << hash.params[:K] if hash.params[:K]
756
- values << hash.params[:V] if hash.params[:V]
757
- end
758
- else
759
- key, value = kv
760
- keys << ((key in [:@label,]) ? KatakataIrb::Types::SYMBOL : simulate_evaluate(key, scope))
761
- values << simulate_evaluate(value, scope)
762
- end
763
- end
764
- KatakataIrb::Types::InstanceType.new(Hash, K: KatakataIrb::Types::UnionType[*keys], V: KatakataIrb::Types::UnionType[*values])
765
- end
766
-
767
- def retrieve_method_call(sexp)
768
- optional = -> { _1 in [:@op, '&.',] }
769
- case sexp
770
- in [:fcall | :vcall, [:@ident | :@const | :@kw | :@op, method,]] # hoge
771
- [nil, method, [], [], nil, false]
772
- in [:call, receiver, [:@period,] | [:@op, '&.',] | [:@op, '::',] | :'::' => dot, :call]
773
- [receiver, :call, [], [], nil, optional[dot]]
774
- in [:call, receiver, [:@period,] | [:@op, '&.',] | [:@op, '::',] | :'::' => dot, method]
775
- method => [:@ident | :@const | :@kw | :@op, method,] unless method == :call
776
- [receiver, method, [], [], nil, optional[dot]]
777
- in [:command, [:@ident | :@const | :@kw | :@op, method,], args] # hoge 1, 2
778
- args, kwargs, block = retrieve_method_args args
779
- [nil, method, args, kwargs, block, false]
780
- in [:command_call, receiver, [:@period,] | [:@op, '&.',] | :'::' => dot, [:@ident | :@const | :@kw | :@op, method,], args] # a.hoge 1; a.hoge 1, 2;
781
- args, kwargs, block = retrieve_method_args args
782
- [receiver, method, args, kwargs, block, optional[dot]]
783
- in [:method_add_arg, call, args]
784
- receiver, method, _arg, _kwarg, _block, opt = retrieve_method_call call
785
- args, kwargs, block = retrieve_method_args args
786
- [receiver, method, args, kwargs, block, opt]
787
- in [:method_add_block, call, block]
788
- receiver, method, args, kwargs, opt = retrieve_method_call call
789
- [receiver, method, args, kwargs, block, opt]
790
- end
791
- end
792
-
793
- def retrieve_method_args(sexp)
794
- case sexp
795
- in [:mrhs_add_star, args, star]
796
- args, = retrieve_method_args args
797
- [[*args, KatakataIrb::Types::Splat.new(star)], [], nil]
798
- in [:mrhs_new_from_args, [:args_add_star,] => args]
799
- args, = retrieve_method_args args
800
- [args, [], nil]
801
- in [:mrhs_new_from_args, [:args_add_star,] => args, last_arg]
802
- args, = retrieve_method_args args
803
- [[*args, last_arg], [], nil]
804
- in [:mrhs_new_from_args, args, last_arg]
805
- [[*args, last_arg], [], nil]
806
- in [:mrhs_new_from_args, args]
807
- [args, [], nil]
808
- in [:args_add_block, [:args_add_star,] => args, block_arg]
809
- args, kwargs, = retrieve_method_args args
810
- block_arg = [:void_stmt] if block_arg.nil? # method(*splat, &)
811
- [args, kwargs, block_arg]
812
- in [:args_add_block, [*args, [:bare_assoc_hash,] => kw], block_arg]
813
- block_arg = [:void_stmt] if block_arg.nil? # method(**splat, &)
814
- _, kwargs = retrieve_method_args kw
815
- [args, kwargs, block_arg]
816
- in [:args_add_block, [*args], block_arg]
817
- block_arg = [:void_stmt] if block_arg.nil? # method(arg, &)
818
- [args, [], block_arg]
819
- in [:bare_assoc_hash, kws]
820
- kwargs = []
821
- kws.each do |kw|
822
- if kw in [:assoc_splat, value,]
823
- kwargs << KatakataIrb::Types::Splat.new(value) if value
824
- elsif kw in [:assoc_new, [:@label, label,] => key, nil]
825
- name = label.delete ':'
826
- kwargs << [key, [:__var_ref_or_call, [name =~ /\A[A-Z]/ ? :@const : :@ident, name, [0, 0]]]]
827
- elsif kw in [:assoc_new, key, value]
828
- kwargs << [key, value]
829
- end
830
- end
831
- [[], kwargs, nil]
832
- in [:args_add_star, *args, [:bare_assoc_hash,] => kwargs]
833
- args, = retrieve_method_args [:args_add_star, *args]
834
- _, kwargs = retrieve_method_args kwargs
835
- [args, kwargs, nil]
836
- in [:args_add_star, pre_args, star_arg, *post_args]
837
- pre_args, = retrieve_method_args pre_args if pre_args in [:args_add_star,]
838
- args = star_arg ? [*pre_args, KatakataIrb::Types::Splat.new(star_arg), *post_args] : pre_args + post_args
839
- [args, [], nil]
840
- in [:arg_paren, args]
841
- args ? retrieve_method_args(args) : [[], [], nil]
842
- in [[:command | :command_call, ] => command_arg] # method(a b, c), method(a.b c, d)
843
- [[command_arg], [], nil]
844
- else
845
- [[], [], nil]
846
- end
847
- end
848
-
849
- def simulate_call(receiver, method_name, args, kwargs, block, name_match: true)
850
- methods = KatakataIrb::Types.rbs_methods receiver, method_name.to_sym, args, kwargs, !!block
851
- block_called = false
852
- type_breaks = methods.map do |method, given_params, method_params|
853
- receiver_vars = (receiver in KatakataIrb::Types::InstanceType) ? receiver.params : {}
854
- free_vars = method.type.free_variables - receiver_vars.keys.to_set
855
- vars = receiver_vars.merge KatakataIrb::Types.match_free_variables(free_vars, method_params, given_params)
856
- if block && method.block
857
- params_type = method.block.type.required_positionals.map do |func_param|
858
- KatakataIrb::Types.from_rbs_type func_param.type, receiver, vars
859
- end
860
- self_type = KatakataIrb::Types.from_rbs_type method.block.self_type, receiver, vars if method.block.self_type
861
- block_response, breaks = block.call params_type, self_type
862
- block_called = true
863
- vars.merge! KatakataIrb::Types.match_free_variables(free_vars - vars.keys.to_set, [method.block.type.return_type], [block_response])
864
- end
865
- [KatakataIrb::Types.from_rbs_type(method.type.return_type, receiver, vars || {}), breaks]
866
- end
867
- block&.call [], nil unless block_called
868
- types = type_breaks.map(&:first)
869
- breaks = type_breaks.map(&:last).compact
870
- types << OBJECT_METHODS[method_name.to_sym] if name_match && OBJECT_METHODS.has_key?(method_name.to_sym)
871
-
872
- if method_name.to_sym == :new
873
- receiver.types.each do |type|
874
- if (type in KatakataIrb::Types::SingletonType) && type.module_or_class.is_a?(Class)
875
- types << KatakataIrb::Types::InstanceType.new(type.module_or_class)
876
- end
877
- end
878
- end
879
- KatakataIrb::Types::UnionType[*types, *breaks]
880
- end
881
-
882
- def extract_param_names(params)
883
- params => [:params, pre_required, optional, rest, post_required, keywords, keyrest, block]
884
- names = []
885
- extract_mlhs = ->(item) do
886
- case item
887
- in [:var_field, [:@ident, name,],]
888
- names << name
889
- in [:@ident, name,]
890
- names << name
891
- in [:mlhs, *items]
892
- items.each(&extract_mlhs)
893
- in [:rest_param, item]
894
- extract_mlhs.call item if item
895
- in [:field | :aref_field,]
896
- # a.b, c[i] = value
897
- in [:excessed_comma]
898
- in [:args_forward]
899
- end
900
- end
901
- [*pre_required, *post_required].each(&extract_mlhs)
902
- extract_mlhs.call rest if rest
903
- optional&.each do |key, _value|
904
- key => [:@ident, name,]
905
- names << name
906
- end
907
- keywords&.each do |key, _value|
908
- key => [:@label, label,]
909
- names << label.delete(':')
910
- end
911
- if keyrest in [:kwrest_params, [:@ident, name,]]
912
- names << name
913
- end
914
- if block in [:blockarg, [:@ident, name,]]
915
- names << name
916
- end
917
- names
918
- end
919
-
920
- def evaluate_assign_params(params, values, scope)
921
- values = values.dup
922
- params => [:params, pre_required, optional, rest, post_required, _keywords, keyrest, block]
923
- size = (pre_required&.size || 0) + (optional&.size || 0) + (post_required&.size || 0) + (rest ? 1 : 0)
924
- values = sized_splat values.first, :to_ary, size if values.size == 1 && size >= 2
925
- pre_values = values.shift pre_required.size if pre_required
926
- post_values = values.pop post_required.size if post_required
927
- opt_values = values.shift optional.size if optional
928
- rest_values = values
929
- evaluate_massign pre_required, pre_values, scope if pre_required
930
- evaluate_massign optional.map(&:first), opt_values, scope if optional
931
- if rest in [:rest_param, [:@ident, name,]]
932
- scope[name] = KatakataIrb::Types::InstanceType.new Array, Elem: KatakataIrb::Types::UnionType[*rest_values]
933
- end
934
- evaluate_massign post_required, post_values, scope if post_required
935
- # TODO: assign keywords
936
- if keyrest in [:kwrest_param, [:@ident, name,]]
937
- scope[name] = KatakataIrb::Types::InstanceType.new Hash, K: KatakataIrb::Types::SYMBOL, V: KatakataIrb::Types::OBJECT
938
- end
939
- if block in [:blockarg, [:@ident, name,]]
940
- scope[name] = KatakataIrb::Types::PROC
941
- end
942
- end
943
-
944
- def evaluate_param_defaults(params, scope)
945
- params => [:params, _pre_required, optional, rest, _post_required, keywords, keyrest, block]
946
- optional&.each do |item, value|
947
- item => [:@ident, name,]
948
- scope[name] = simulate_evaluate value, scope
949
- end
950
- if rest in [:rest_param, [:@ident, name,]]
951
- scope[name] = KatakataIrb::Types::ARRAY
952
- end
953
- keywords&.each do |key, value|
954
- key => [:@label, label,]
955
- name = label.delete ':'
956
- scope[name] = value ? simulate_evaluate(value, scope) : KatakataIrb::Types::OBJECT
957
- end
958
- if keyrest in [:kwrest_param, [:@ident, name,]]
959
- scope[name] = KatakataIrb::Types::HASH
960
- end
961
- if block in [:blockarg, [:@ident, name,]]
962
- scope[name] = KatakataIrb::Types::PROC
963
- end
964
- end
965
-
966
- def max_numbered_params(sexp)
967
- case sexp
968
- in [:do_block | :brace_block | :def | :class | :module,]
969
- 0
970
- in [:var_ref, [:@ident, name,]]
971
- name.match?(/\A_[1-9]\z/) ? name[1..].to_i : 0
972
- else
973
- sexp.filter_map do |s|
974
- max_numbered_params s if s.is_a? Array
975
- end.max || 0
976
- end
977
- end
978
-
979
- def self.calculate_binding_scope(binding, parents, target)
980
- dig_targets = DigTarget.new(parents, target) do |_types, scope|
981
- return scope
982
- end
983
- scope = KatakataIrb::Scope.from_binding(binding)
984
- new(dig_targets).simulate_evaluate parents[0], scope
985
- scope
986
- end
987
-
988
- def self.calculate_receiver(binding, parents, receiver)
989
- dig_targets = DigTarget.new(parents, receiver) do |type, _scope|
990
- return type
991
- end
992
- new(dig_targets).simulate_evaluate parents[0], KatakataIrb::Scope.from_binding(binding)
993
- KatakataIrb::Types::NIL
994
- end
995
- end