katakata_irb 0.1.12 → 0.2.1

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.
@@ -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