katakata_irb 0.1.3 → 0.1.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.
@@ -1,6 +1,7 @@
1
- require_relative 'types'
2
1
  require 'ripper'
3
2
  require 'set'
3
+ require_relative 'types'
4
+ require_relative 'scope'
4
5
 
5
6
  class KatakataIrb::TypeSimulator
6
7
  class DigTarget
@@ -17,234 +18,12 @@ class KatakataIrb::TypeSimulator
17
18
  end
18
19
  end
19
20
 
20
- class BaseScope
21
- def initialize(binding, self_object)
22
- @binding, @self_object = binding, self_object
23
- @cache = { SELF => KatakataIrb::Types.type_from_object(self_object) }
24
- @local_variables = binding.local_variables.map(&:to_s).to_set
25
- end
26
-
27
- def mutable?() = false
28
-
29
- def [](name)
30
- @cache[name] ||= (
31
- fallback = KatakataIrb::Types::NIL
32
- case BaseScope.type_by_name name
33
- when :cvar
34
- KatakataIrb::TypeSimulator.type_of(fallback:) { @self_object.class_variable_get name }
35
- when :ivar
36
- KatakataIrb::TypeSimulator.type_of(fallback:) { @self_object.instance_variable_get name }
37
- when :lvar
38
- KatakataIrb::TypeSimulator.type_of(fallback:) { @binding.local_variable_get(name) }
39
- when :const
40
- KatakataIrb::TypeSimulator.type_of(fallback:) { @binding.eval name }
41
- end
42
- )
43
- end
44
-
45
- def self_type
46
- self[SELF]
47
- end
48
-
49
- def local_variables
50
- @local_variables.to_a
51
- end
52
-
53
- def self.type_by_name(name)
54
- if name.start_with? '@@'
55
- :cvar
56
- elsif name.start_with? '@'
57
- :ivar
58
- elsif name.start_with? '$'
59
- :gvar
60
- elsif name.start_with? '%'
61
- :internal
62
- elsif name[0].downcase != name[0]
63
- :const
64
- else
65
- :lvar
66
- end
67
- end
68
-
69
- def has?(name)
70
- case BaseScope.type_by_name name
71
- when :cvar
72
- @self_object.class_variable_defined? name
73
- when :ivar
74
- @self_object.instance_variable_defined? name
75
- when :lvar
76
- @local_variables.include? name
77
- when :const
78
- @binding.eval("#{name};true") rescue false
79
- when :internal
80
- true
81
- end
82
- end
83
- end
84
-
85
- class Scope
86
- attr_reader :parent, :jump_branches
87
-
88
- def self.from_binding(binding) = new BaseScope.new(binding, binding.eval('self'))
89
-
90
- def initialize(parent, table = {}, trace_cvar: true, trace_ivar: true, trace_lvar: true, passthrough: false)
91
- @tables = [table]
92
- @parent = parent
93
- @trace_cvar = trace_cvar
94
- @trace_ivar = trace_ivar
95
- @trace_lvar = trace_lvar
96
- @passthrough = passthrough
97
- @terminated = false
98
- @jump_branches = []
99
- end
100
-
101
- def mutable? = true
102
-
103
- def terminated?
104
- @terminated
105
- end
106
-
107
- def terminate_with(type, value)
108
- return if terminated?
109
- self[type] = value
110
- store_jump type
111
- terminate
112
- end
113
-
114
- def store_jump(type)
115
- scopes = ancestors.select(&:mutable?)
116
- scope = scopes.find { _1.has_own? type } || scopes.last
117
- index = scopes.index scope
118
- scope.jump_branches << scopes.drop(index).map(&:branch_table_clone)
119
- end
120
-
121
- def terminate
122
- @terminated = true
123
- end
124
-
125
- def branch_table_clone() = @tables.last.dup
126
-
127
- def trace?(name)
128
- return false unless @parent
129
- type = BaseScope.type_by_name(name)
130
- type == :cvar ? @trace_cvar : type == :ivar ? @trace_ivar : type == :lvar ? @trace_lvar : true
131
- end
132
-
133
- def [](name)
134
- @tables.reverse_each do |table|
135
- return table[name] if table.key? name
136
- end
137
- @parent[name] if trace? name
138
- end
139
-
140
- def []=(name, type)
141
- if @passthrough && BaseScope.type_by_name(name) != :internal
142
- @parent[name] = type
143
- elsif trace?(name) && @parent.mutable? && !@tables.any? { _1.key? name } && @parent.has?(name)
144
- @parent[name] = type
145
- else
146
- @tables.last[name] = type
147
- end
148
- end
149
-
150
- def self_type
151
- self[SELF]
152
- end
153
-
154
- def local_variables
155
- lvar_keys = @tables.flat_map(&:keys).select do |name|
156
- BaseScope.type_by_name(name) == :lvar
157
- end
158
- lvar_keys |= @parent.local_variables if @trace_lvar
159
- lvar_keys
160
- end
161
-
162
- def start_branch
163
- @tables << {}
164
- end
165
-
166
- def end_branch
167
- @tables.pop
168
- end
169
-
170
- def merge_jumps
171
- if terminated?
172
- merge @jump_branches
173
- else
174
- merge [*@jump_branches, [{}] * ancestors.size]
175
- end
176
- end
177
-
178
- def merge_branch(tables)
179
- target_table = @tables.last
180
- keys = tables.flat_map(&:keys).uniq
181
- keys.each do |key|
182
- original_value = self[key] || KatakataIrb::Types::NIL
183
- target_table[key] = KatakataIrb::Types::UnionType[*tables.map { _1[key] || original_value }.uniq]
184
- end
185
- end
186
-
187
- def ancestors
188
- scopes = [self]
189
- scopes << scopes.last.parent while scopes.last.parent&.mutable?
190
- scopes
191
- end
192
-
193
- def conditional(&block)
194
- run_branches(block, -> {}).first || KatakataIrb::Types::NIL
195
- end
196
-
197
- def never(&block)
198
- branch(&block)
199
- end
200
-
201
- def run_branches(*blocks)
202
- results = blocks.map { branch(&_1) }.reject(&:last)
203
- merge results.map { _2 }
204
- if results.empty?
205
- terminate
206
- []
207
- else
208
- results.map(&:first)
209
- end
210
- end
211
-
212
- def branch
213
- scopes = ancestors
214
- scopes.each(&:start_branch)
215
- @terminated = false
216
- result = yield
217
- terminated = @terminated
218
- @terminated = false
219
- [result, scopes.map(&:end_branch), terminated]
220
- end
221
-
222
- def merge(branches)
223
- scopes = ancestors
224
- scopes.zip(*branches).each do |scope, *tables|
225
- scope.merge_branch(tables)
226
- end
227
- end
228
-
229
- def base_scope
230
- @parent&.mutable? ? @parent.base_scope : @parent
231
- end
232
-
233
- def has_own?(name)
234
- @tables.any? { _1.key? name }
235
- end
236
-
237
- def has?(name)
238
- has_own?(name) || (trace?(name) && @parent.has?(name))
239
- end
240
- end
241
-
242
21
  module LexerElemMatcher
243
22
  refine Ripper::Lexer::Elem do
244
23
  def deconstruct_keys(_keys)
245
24
  {
246
- tok:,
247
- event:,
25
+ tok: tok,
26
+ event: event,
248
27
  label: state.allbits?(Ripper::EXPR_LABEL),
249
28
  beg: state.allbits?(Ripper::EXPR_BEG),
250
29
  dot: state.allbits?(Ripper::EXPR_DOT)
@@ -268,19 +47,12 @@ class KatakataIrb::TypeSimulator
268
47
  to_r: KatakataIrb::Types::RATIONAL
269
48
  }
270
49
 
271
- SELF = '%self'
272
- BREAK_RESULT = '%break'
273
- NEXT_RESULT = '%next'
274
- RETURN_RESULT = '%return'
275
- PATTERNMATCH_BREAK = '%match'
276
- RAISE_BREAK = '%raise'
277
-
278
50
  def initialize(dig_targets)
279
51
  @dig_targets = dig_targets
280
52
  end
281
53
 
282
54
  def simulate_evaluate(sexp, scope, case_target: nil)
283
- result = simulate_evaluate_inner(sexp, scope, case_target:)
55
+ result = simulate_evaluate_inner(sexp, scope, case_target: case_target)
284
56
  @dig_targets.resolve result, scope if @dig_targets.target?(sexp)
285
57
  result
286
58
  end
@@ -309,10 +81,16 @@ class KatakataIrb::TypeSimulator
309
81
  if @dig_targets.dig? sexp
310
82
  params in [:paren, params]
311
83
  params_table = extract_param_names(params).to_h { [_1, KatakataIrb::Types::NIL] }
312
- method_scope = Scope.new scope, { **params_table, SELF => self_type, BREAK_RESULT => nil, NEXT_RESULT => nil, RETURN_RESULT => nil }, trace_lvar: false
84
+ method_scope = KatakataIrb::Scope.new(
85
+ scope,
86
+ { **params_table, KatakataIrb::Scope::SELF => self_type, KatakataIrb::Scope::BREAK_RESULT => nil, KatakataIrb::Scope::NEXT_RESULT => nil, KatakataIrb::Scope::RETURN_RESULT => nil },
87
+ trace_lvar: false
88
+ )
313
89
  evaluate_assign_params params, [], method_scope
314
- method_scope.conditional { evaluate_param_defaults params, method_scope }
90
+ method_scope.conditional { evaluate_param_defaults params, _1 }
315
91
  simulate_evaluate body_stmt, method_scope
92
+ method_scope.merge_jumps
93
+ scope.update method_scope
316
94
  end
317
95
  KatakataIrb::Types::SYMBOL
318
96
  in [:@int,]
@@ -414,7 +192,7 @@ class KatakataIrb::TypeSimulator
414
192
  statements.map { simulate_evaluate _1, scope }.last
415
193
  in [:const_path_ref, receiver, [:@const, name,]]
416
194
  r = simulate_evaluate receiver, scope
417
- (r in KatakataIrb::Types::SingletonType) ? self.class.type_of { r.module_or_class.const_get name } : KatakataIrb::Types::NIL
195
+ (r in KatakataIrb::Types::SingletonType) ? KatakataIrb::BaseScope.type_of { r.module_or_class.const_get name } : KatakataIrb::Types::NIL
418
196
  in [:__var_ref_or_call, [type, name, pos]]
419
197
  sexp = scope.has?(name) ? [:var_ref, [type, name, pos]] : [:vcall, [:@ident, name, pos]]
420
198
  simulate_evaluate sexp, scope
@@ -456,13 +234,13 @@ class KatakataIrb::TypeSimulator
456
234
  # workaround for https://bugs.ruby-lang.org/issues/19175
457
235
  return scope[name]
458
236
  end
459
- receiver, method, args, kwargs, block, conditional = retrieve_method_call sexp
237
+ receiver, method, args, kwargs, block, optional_chain = retrieve_method_call sexp
460
238
  if receiver.nil? && method == 'raise'
461
- scope.terminate_with RAISE_BREAK, KatakataIrb::Types::TRUE
239
+ scope.terminate_with KatakataIrb::Scope::RAISE_BREAK, KatakataIrb::Types::TRUE
462
240
  return KatakataIrb::Types::NIL
463
241
  end
464
242
  receiver_type = receiver ? simulate_evaluate(receiver, scope) : scope.self_type
465
- evaluate_method = lambda do
243
+ evaluate_method = lambda do |scope|
466
244
  args_type = args.map do |arg|
467
245
  if arg in KatakataIrb::Types::Splat
468
246
  simulate_evaluate arg.item, scope
@@ -474,14 +252,14 @@ class KatakataIrb::TypeSimulator
474
252
 
475
253
  if block
476
254
  if block in [:symbol_literal, [:symbol, [:@ident, block_name,]]]
477
- call_block_proc = ->(block_args) do
255
+ call_block_proc = ->(block_args, _self_type) do
478
256
  block_receiver, *rest = block_args
479
257
  block_receiver ? simulate_call(block_receiver || KatakataIrb::Types::OBJECT, block_name, rest, nil, nil) : KatakataIrb::Types::OBJECT
480
258
  end
481
259
  elsif block in [:do_block | :brace_block => type, block_var, body]
482
260
  block_var in [:block_var, params,]
483
- call_block_proc = ->(block_args) do
484
- result, breaks, nexts = scope.conditional do
261
+ call_block_proc = ->(block_args, block_self_type) do
262
+ scope.conditional do |s|
485
263
  if params
486
264
  names = extract_param_names(params)
487
265
  else
@@ -489,40 +267,52 @@ class KatakataIrb::TypeSimulator
489
267
  params = [:params, names.map { [:@ident, _1, [0, 0]] }, nil, nil, nil, nil, nil, nil]
490
268
  end
491
269
  params_table = names.zip(block_args).to_h { [_1, _2 || KatakataIrb::Types::NIL] }
492
- block_scope = Scope.new scope, { **params_table, BREAK_RESULT => nil, NEXT_RESULT => nil }
270
+ table = { **params_table, KatakataIrb::Scope::BREAK_RESULT => nil, KatakataIrb::Scope::NEXT_RESULT => nil }
271
+ table[KatakataIrb::Scope::SELF] = block_self_type if block_self_type
272
+ block_scope = KatakataIrb::Scope.new s, table
493
273
  evaluate_assign_params params, block_args, block_scope
494
- block_scope.conditional { evaluate_param_defaults params, block_scope } if params
274
+ block_scope.conditional { evaluate_param_defaults params, _1 } if params
495
275
  if type == :do_block
496
276
  result = simulate_evaluate body, block_scope
497
277
  else
498
278
  result = body.map { simulate_evaluate _1, block_scope }.last
499
279
  end
500
280
  block_scope.merge_jumps
501
- result = KatakataIrb::Types::NIL if block_scope.terminated?
502
- [result, block_scope[BREAK_RESULT], block_scope[NEXT_RESULT]]
281
+ s.update block_scope
282
+ nexts = block_scope[KatakataIrb::Scope::NEXT_RESULT]
283
+ breaks = block_scope[KatakataIrb::Scope::BREAK_RESULT]
284
+ if block_scope.terminated?
285
+ [KatakataIrb::Types::UnionType[*nexts], breaks]
286
+ else
287
+ [KatakataIrb::Types::UnionType[result, *nexts], breaks]
288
+ end
503
289
  end
504
- [KatakataIrb::Types::UnionType[result, *nexts], breaks]
505
290
  end
506
291
  else
507
- call_block_proc = ->(_block_args) { KatakataIrb::Types::OBJECT }
292
+ call_block_proc = ->(_block_args, _self_type) { KatakataIrb::Types::OBJECT }
508
293
  simulate_evaluate block, scope
509
294
  end
510
295
  end
511
296
  simulate_call receiver_type, method, args_type, kwargs_type(kwargs, scope), call_block_proc
512
297
  end
513
- if conditional
514
- scope.conditional { evaluate_method.call }
298
+ if optional_chain
299
+ result = scope.conditional { evaluate_method.call _1 }
300
+ if receiver_type.nillable?
301
+ KatakataIrb::Types::UnionType[result, KatakataIrb::Types::NIL]
302
+ else
303
+ result
304
+ end
515
305
  else
516
- evaluate_method.call
306
+ evaluate_method.call scope
517
307
  end
518
308
  in [:binary, a, Symbol => op, b]
519
309
  atype = simulate_evaluate a, scope
520
310
  case op
521
311
  when :'&&', :and
522
- btype = scope.conditional { simulate_evaluate b, scope }
312
+ btype = scope.conditional { simulate_evaluate b, _1 }
523
313
  KatakataIrb::Types::UnionType[btype, KatakataIrb::Types::NIL, KatakataIrb::Types::FALSE]
524
314
  when :'||', :or
525
- btype = scope.conditional { simulate_evaluate b, scope }
315
+ btype = scope.conditional { simulate_evaluate b, _1 }
526
316
  KatakataIrb::Types::UnionType[atype, btype]
527
317
  else
528
318
  btype = simulate_evaluate b, scope
@@ -535,11 +325,14 @@ class KatakataIrb::TypeSimulator
535
325
  statements in [:bodystmt, statements, _unknown, _unknown, _unknown] # -> do end
536
326
  params in [:paren, params]
537
327
  params_table = extract_param_names(params).to_h { [_1, KatakataIrb::Types::NIL] }
538
- block_scope = Scope.new scope, { **params_table, BREAK_RESULT => nil, NEXT_RESULT => nil, RETURN_RESULT => nil }
539
- evaluate_assign_params params, [], block_scope
540
- block_scope.conditional { evaluate_param_defaults params, block_scope }
541
- statements.each { simulate_evaluate _1, block_scope }
328
+ block_scope = KatakataIrb::Scope.new scope, { **params_table, KatakataIrb::Scope::BREAK_RESULT => nil, KatakataIrb::Scope::NEXT_RESULT => nil, KatakataIrb::Scope::RETURN_RESULT => nil }
329
+ block_scope.conditional do |s|
330
+ evaluate_assign_params params, [], s
331
+ s.conditional { evaluate_param_defaults params, _1 }
332
+ statements.each { simulate_evaluate _1, s }
333
+ end
542
334
  block_scope.merge_jumps
335
+ scope.update block_scope
543
336
  KatakataIrb::Types::ProcType.new
544
337
  in [:assign, [:var_field, [:@gvar | :@ivar | :@cvar | :@ident | :@const, name,]], value]
545
338
  res = simulate_evaluate value, scope
@@ -587,35 +380,37 @@ class KatakataIrb::TypeSimulator
587
380
  in [:ifop, cond, tval, fval]
588
381
  simulate_evaluate cond, scope
589
382
  KatakataIrb::Types::UnionType[*scope.run_branches(
590
- -> { simulate_evaluate tval, scope },
591
- -> { simulate_evaluate fval, scope }
383
+ -> { simulate_evaluate tval, _1 },
384
+ -> { simulate_evaluate fval, _1 }
592
385
  )]
593
386
  in [:if_mod | :unless_mod, cond, statement]
594
387
  simulate_evaluate cond, scope
595
- KatakataIrb::Types::UnionType[scope.conditional { simulate_evaluate statement, scope }, KatakataIrb::Types::NIL]
388
+ KatakataIrb::Types::UnionType[scope.conditional { simulate_evaluate statement, _1 }, KatakataIrb::Types::NIL]
596
389
  in [:if | :unless | :elsif, cond, statements, else_statement]
597
390
  simulate_evaluate cond, scope
598
391
  results = scope.run_branches(
599
- -> { statements.map { simulate_evaluate _1, scope }.last },
600
- -> { else_statement ? simulate_evaluate(else_statement, scope) : KatakataIrb::Types::NIL }
392
+ ->(s) { statements.map { simulate_evaluate _1, s }.last },
393
+ ->(s) { else_statement ? simulate_evaluate(else_statement, s) : KatakataIrb::Types::NIL }
601
394
  )
602
395
  results.empty? ? KatakataIrb::Types::NIL : KatakataIrb::Types::UnionType[*results]
603
396
  in [:while | :until, cond, statements]
604
- inner_scope = Scope.new scope, { BREAK_RESULT => nil }, passthrough: true
397
+ inner_scope = KatakataIrb::Scope.new scope, { KatakataIrb::Scope::BREAK_RESULT => nil }, passthrough: true
605
398
  simulate_evaluate cond, inner_scope
606
- scope.conditional { statements.each { simulate_evaluate _1, inner_scope } }
399
+ inner_scope.conditional { |s| statements.each { simulate_evaluate _1, s } }
607
400
  inner_scope.merge_jumps
608
- breaks = inner_scope[BREAK_RESULT]
401
+ scope.update inner_scope
402
+ breaks = inner_scope[KatakataIrb::Scope::BREAK_RESULT]
609
403
  breaks ? KatakataIrb::Types::UnionType[breaks, KatakataIrb::Types::NIL] : KatakataIrb::Types::NIL
610
404
  in [:while_mod | :until_mod, cond, statement]
611
- inner_scope = Scope.new scope, { BREAK_RESULT => nil }, passthrough: true
405
+ inner_scope = KatakataIrb::Scope.new scope, { KatakataIrb::Scope::BREAK_RESULT => nil }, passthrough: true
612
406
  simulate_evaluate cond, inner_scope
613
- scope.conditional { simulate_evaluate statement, inner_scope }
407
+ inner_scope.conditional { |s| simulate_evaluate statement, s }
614
408
  inner_scope.merge_jumps
615
- breaks = inner_scope[BREAK_RESULT]
409
+ scope.update inner_scope
410
+ breaks = inner_scope[KatakataIrb::Scope::BREAK_RESULT]
616
411
  breaks ? KatakataIrb::Types::UnionType[breaks, KatakataIrb::Types::NIL] : KatakataIrb::Types::NIL
617
412
  in [:break | :next | :return => jump_type, value]
618
- internal_key = jump_type == :break ? BREAK_RESULT : jump_type == :next ? NEXT_RESULT : RETURN_RESULT
413
+ internal_key = jump_type == :break ? KatakataIrb::Scope::BREAK_RESULT : jump_type == :next ? KatakataIrb::Scope::NEXT_RESULT : KatakataIrb::Scope::RETURN_RESULT
619
414
  if value.empty?
620
415
  jump_value = KatakataIrb::Types::NIL
621
416
  else
@@ -626,7 +421,7 @@ class KatakataIrb::TypeSimulator
626
421
  scope.terminate_with internal_key, jump_value
627
422
  KatakataIrb::Types::NIL
628
423
  in [:return0]
629
- scope.terminate_with RETURN_RESULT, KatakataIrb::Types::NIL
424
+ scope.terminate_with KatakataIrb::Scope::RETURN_RESULT, KatakataIrb::Types::NIL
630
425
  KatakataIrb::Types::NIL
631
426
  in [:yield, args]
632
427
  evaluate_mrhs args, scope
@@ -635,6 +430,8 @@ class KatakataIrb::TypeSimulator
635
430
  KatakataIrb::Types::OBJECT
636
431
  in [:redo | :retry]
637
432
  scope.terminate
433
+ in [:zsuper]
434
+ KatakataIrb::Types::OBJECT
638
435
  in [:super, args]
639
436
  args, kwargs, _block = retrieve_method_args args
640
437
  args.each do |arg|
@@ -647,47 +444,55 @@ class KatakataIrb::TypeSimulator
647
444
  simulate_evaluate body_stmt, scope
648
445
  in [:bodystmt, statements, rescue_stmt, _unknown, ensure_stmt]
649
446
  statements = [statements] if statements in [Symbol,] # oneliner-def body
650
- rescue_scope = Scope.new scope, { RAISE_BREAK => nil }, passthrough: true if rescue_stmt
447
+ rescue_scope = KatakataIrb::Scope.new scope, { KatakataIrb::Scope::RAISE_BREAK => nil }, passthrough: true if rescue_stmt
651
448
  return_type = statements.map { simulate_evaluate _1, rescue_scope || scope }.last
652
- rescue_scope&.merge_jumps
653
449
  if rescue_stmt
654
- return_type = KatakataIrb::Types::UnionType[return_type, scope.conditional { simulate_evaluate rescue_stmt, scope }]
450
+ rescue_scope.merge_jumps
451
+ scope.update rescue_scope
452
+ return_type = KatakataIrb::Types::UnionType[return_type, scope.conditional { simulate_evaluate rescue_stmt, _1 }]
655
453
  end
656
454
  simulate_evaluate ensure_stmt, scope if ensure_stmt
657
455
  return_type
658
456
  in [:rescue, error_class_stmts, error_var_stmt, statements, rescue_stmt]
659
- return_type = scope.conditional do
457
+ return_type = scope.conditional do |s|
660
458
  if error_var_stmt in [:var_field, [:@ident, error_var,]]
661
459
  if (error_class_stmts in [:mrhs_new_from_args, Array => stmts, stmt])
662
460
  error_class_stmts = [*stmts, stmt]
663
461
  end
664
- error_classes = (error_class_stmts || []).flat_map { simulate_evaluate _1, scope }.uniq
462
+ error_classes = (error_class_stmts || []).flat_map { simulate_evaluate _1, s }.uniq
665
463
  error_types = error_classes.filter_map { KatakataIrb::Types::InstanceType.new _1.module_or_class if _1 in KatakataIrb::Types::SingletonType }
666
464
  error_types << KatakataIrb::Types::InstanceType.new(StandardError) if error_types.empty?
667
- scope[error_var] = KatakataIrb::Types::UnionType[*error_types]
465
+ s[error_var] = KatakataIrb::Types::UnionType[*error_types]
668
466
  end
669
- statements.map { simulate_evaluate _1, scope }.last
467
+ statements.map { simulate_evaluate _1, s }.last
670
468
  end
671
469
  if rescue_stmt
672
- return_type = KatakataIrb::Types::UnionType[return_type, scope.conditional { simulate_evaluate rescue_stmt, scope }]
470
+ return_type = KatakataIrb::Types::UnionType[return_type, scope.conditional { simulate_evaluate rescue_stmt, _1 }]
673
471
  end
674
472
  return_type
675
473
  in [:rescue_mod, statement1, statement2]
676
- rescue_scope = Scope.new scope, { RAISE_BREAK => nil }, passthrough: true
474
+ rescue_scope = KatakataIrb::Scope.new scope, { KatakataIrb::Scope::RAISE_BREAK => nil }, passthrough: true
677
475
  a = simulate_evaluate statement1, rescue_scope
678
476
  rescue_scope.merge_jumps
679
- b = scope.conditional { simulate_evaluate statement2, scope }
477
+ scope.update rescue_scope
478
+ b = scope.conditional { simulate_evaluate statement2, _1 }
680
479
  KatakataIrb::Types::UnionType[a, b]
681
480
  in [:module, module_stmt, body_stmt]
682
481
  module_types = simulate_evaluate(module_stmt, scope).types.grep(KatakataIrb::Types::SingletonType)
683
482
  module_types << KatakataIrb::Types::MODULE if module_types.empty?
684
- simulate_evaluate body_stmt, Scope.new(scope, { SELF => KatakataIrb::Types::UnionType[*module_types], BREAK_RESULT => nil, NEXT_RESULT => nil, RETURN_RESULT => nil }, trace_cvar: false, trace_ivar: false, trace_lvar: false)
483
+ 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)
484
+ result = simulate_evaluate body_stmt, module_scope
485
+ scope.update module_scope
486
+ result
685
487
  in [:sclass, klass_stmt, body_stmt]
686
488
  klass_types = simulate_evaluate(klass_stmt, scope).types.filter_map do |type|
687
489
  KatakataIrb::Types::SingletonType.new type.klass if type in KatakataIrb::Types::InstanceType
688
490
  end
689
491
  klass_types = [KatakataIrb::Types::CLASS] if klass_types.empty?
690
- simulate_evaluate body_stmt, Scope.new(scope, { SELF => KatakataIrb::Types::UnionType[*klass_types], BREAK_RESULT => nil, NEXT_RESULT => nil, RETURN_RESULT => nil }, trace_cvar: false, trace_ivar: false, trace_lvar: false)
492
+ 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)
493
+ result = simulate_evaluate body_stmt, sclass_scope
494
+ scope.update sclass_scope
495
+ result
691
496
  in [:class, klass_stmt, superclass_stmt, body_stmt]
692
497
  klass_types = simulate_evaluate(klass_stmt, scope).types
693
498
  klass_types += simulate_evaluate(superclass_stmt, scope).types if superclass_stmt
@@ -695,7 +500,10 @@ class KatakataIrb::TypeSimulator
695
500
  (type in KatakataIrb::Types::SingletonType) && type.module_or_class.is_a?(Class)
696
501
  end
697
502
  klass_types << KatakataIrb::Types::CLASS if klass_types.empty?
698
- simulate_evaluate body_stmt, Scope.new(scope, { SELF => KatakataIrb::Types::UnionType[*klass_types], BREAK_RESULT => nil, NEXT_RESULT => nil, RETURN_RESULT => nil }, trace_cvar: false, trace_ivar: false, trace_lvar: false)
503
+ 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)
504
+ result = simulate_evaluate body_stmt, klass_scope
505
+ scope.update klass_scope
506
+ result
699
507
  in [:for, fields, enum, statements]
700
508
  fields = [fields] if fields in [:var_field | :field | :aref_field,]
701
509
  params = [:params, fields, nil, nil, nil, nil, nil, nil]
@@ -703,47 +511,49 @@ class KatakataIrb::TypeSimulator
703
511
  extract_param_names(params).each { scope[_1] = KatakataIrb::Types::NIL }
704
512
  response = simulate_call enum, :first, [], nil, nil
705
513
  evaluate_assign_params params, [response], scope
706
- inner_scope = Scope.new scope, { BREAK_RESULT => nil }, passthrough: true
707
- scope.conditional do
708
- statements.each { simulate_evaluate _1, inner_scope }
514
+ inner_scope = KatakataIrb::Scope.new scope, { KatakataIrb::Scope::BREAK_RESULT => nil }, passthrough: true
515
+ scope.conditional do |s|
516
+ statements.each { simulate_evaluate _1, s }
709
517
  end
710
518
  inner_scope.merge_jumps
711
- breaks = inner_scope[BREAK_RESULT]
519
+ scope.update inner_scope
520
+ breaks = inner_scope[KatakataIrb::Scope::BREAK_RESULT]
712
521
  breaks ? KatakataIrb::Types::UnionType[breaks, enum] : enum
713
522
  in [:when, pattern, if_statements, else_statement]
714
- eval_pattern = lambda do |pattern, *rest|
715
- simulate_evaluate pattern, scope
716
- scope.conditional { eval_pattern.call(*rest) } if rest.any?
523
+ eval_pattern = lambda do |s, pattern, *rest|
524
+ simulate_evaluate pattern, s
525
+ scope.conditional { eval_pattern.call(_1, *rest) } if rest.any?
717
526
  end
718
- if_branch = lambda do
719
- eval_pattern.call(*pattern)
720
- if_statements.map { simulate_evaluate _1, scope }.last
527
+ if_branch = lambda do |s|
528
+ eval_pattern.call(s, *pattern)
529
+ if_statements.map { simulate_evaluate _1, s }.last
721
530
  end
722
- else_branch = lambda do
723
- pattern.each { simulate_evaluate _1, scope }
724
- simulate_evaluate(else_statement, scope, case_target:)
531
+ else_branch = lambda do |s|
532
+ pattern.each { simulate_evaluate _1, s }
533
+ simulate_evaluate(else_statement, s, case_target: case_target)
725
534
  end
726
535
  if if_statements && else_statement
727
536
  KatakataIrb::Types::UnionType[*scope.run_branches(if_branch, else_branch)]
728
537
  else
729
- KatakataIrb::Types::UnionType[scope.conditional { (if_branch || else_branch).call }, KatakataIrb::Types::NIL]
538
+ KatakataIrb::Types::UnionType[scope.conditional { (if_branch || else_branch).call _1 }, KatakataIrb::Types::NIL]
730
539
  end
731
540
  in [:in, [:var_field, [:@ident, name,]], if_statements, else_statement]
732
541
  scope.never { simulate_evaluate else_statement, scope } if else_statement
733
542
  scope[name] = case_target || KatakataIrb::Types::OBJECT
734
543
  if_statements ? if_statements.map { simulate_evaluate _1, scope }.last : KatakataIrb::Types::NIL
735
544
  in [:in, pattern, if_statements, else_statement]
736
- pattern_scope = Scope.new(scope, { PATTERNMATCH_BREAK => nil }, passthrough: true)
737
- results = scope.run_branches(
738
- -> {
739
- match_pattern case_target, pattern, pattern_scope
740
- if_statements ? if_statements.map { simulate_evaluate _1, scope }.last : KatakataIrb::Types::NIL
545
+ pattern_scope = KatakataIrb::Scope.new(scope, { KatakataIrb::Scope::PATTERNMATCH_BREAK => nil }, passthrough: true)
546
+ results = pattern_scope.run_branches(
547
+ ->(s) {
548
+ match_pattern case_target, pattern, s
549
+ if_statements ? if_statements.map { simulate_evaluate _1, s }.last : KatakataIrb::Types::NIL
741
550
  },
742
- -> {
743
- pattern_scope.merge_jumps
744
- else_statement ? simulate_evaluate(else_statement, scope, case_target:) : KatakataIrb::Types::NIL
551
+ ->(s) {
552
+ else_statement ? simulate_evaluate(else_statement, s, case_target: case_target) : KatakataIrb::Types::NIL
745
553
  }
746
554
  )
555
+ pattern_scope.merge_jumps
556
+ scope.update pattern_scope
747
557
  KatakataIrb::Types::UnionType[*results]
748
558
  in [:case, target_exp, match_exp]
749
559
  target = simulate_evaluate target_exp, scope
@@ -751,11 +561,16 @@ class KatakataIrb::TypeSimulator
751
561
  in [:void_stmt]
752
562
  KatakataIrb::Types::NIL
753
563
  in [:dot2 | :dot3, range_beg, range_end]
754
- simulate_evaluate range_beg, scope if range_beg
755
- simulate_evaluate range_end, scope if range_end
756
- KatakataIrb::Types::RANGE
564
+ beg_type = simulate_evaluate range_beg, scope if range_beg
565
+ end_type = simulate_evaluate range_end, scope if range_end
566
+ elem = (KatakataIrb::Types::UnionType[*[beg_type, end_type].compact]).nonnillable
567
+ KatakataIrb::Types::InstanceType.new Range, { Elem: elem }
757
568
  in [:top_const_ref, [:@const, name,]]
758
- self.class.type_of { Object.const_get name }
569
+ KatakataIrb::BaseScope.type_of { Object.const_get name }
570
+ in [:string_concat, a, b]
571
+ simulate_evaluate a, scope
572
+ simulate_evaluate b, scope
573
+ KatakataIrb::Types::STRING
759
574
  else
760
575
  KatakataIrb.log_puts
761
576
  KatakataIrb.log_puts :NOMATCH
@@ -765,7 +580,7 @@ class KatakataIrb::TypeSimulator
765
580
  end
766
581
 
767
582
  def match_pattern(target, pattern, scope)
768
- breakable = -> { scope.store_jump PATTERNMATCH_BREAK }
583
+ breakable = -> { scope.terminate_with KatakataIrb::Scope::PATTERNMATCH_BREAK, KatakataIrb::Types::NIL }
769
584
  types = target.types
770
585
  case pattern
771
586
  in [:var_field, [:@ident, name,]]
@@ -777,7 +592,7 @@ class KatakataIrb::TypeSimulator
777
592
  breakable.call
778
593
  in [:binary, lpattern, :|, rpattern]
779
594
  match_pattern target, lpattern, scope
780
- scope.conditional { match_pattern target, rpattern, scope }
595
+ scope.conditional { match_pattern target, rpattern, _1 }
781
596
  breakable.call
782
597
  in [:binary, lpattern, :'=>', [:var_field, [:@ident, name,]] => rpattern]
783
598
  if lpattern in [:var_ref, [:@const, _const_name,]]
@@ -892,7 +707,7 @@ class KatakataIrb::TypeSimulator
892
707
  in [:@ident, name,]
893
708
  # block arg mlhs
894
709
  scope[name] = value || KatakataIrb::Types::OBJECT
895
- in [:var_field, [:@ident | :@ivar | :@cvar | :@gvar, name,]]
710
+ in [:var_field, [:@gvar | :@ivar | :@cvar | :@ident | :@const, name,]]
896
711
  # massign
897
712
  scope[name] = value || KatakataIrb::Types::OBJECT
898
713
  in [:mlhs, *mlhs]
@@ -932,37 +747,29 @@ class KatakataIrb::TypeSimulator
932
747
  KatakataIrb::Types::InstanceType.new(Hash, K: KatakataIrb::Types::UnionType[*keys], V: KatakataIrb::Types::UnionType[*values])
933
748
  end
934
749
 
935
- def self.type_of(fallback: KatakataIrb::Types::OBJECT)
936
- begin
937
- KatakataIrb::Types.type_from_object yield
938
- rescue
939
- fallback
940
- end
941
- end
942
-
943
750
  def retrieve_method_call(sexp)
944
- conditional = -> { _1 in [:@op, '&.',] }
751
+ optional = -> { _1 in [:@op, '&.',] }
945
752
  case sexp
946
753
  in [:fcall | :vcall, [:@ident | :@const | :@kw | :@op, method,]] # hoge
947
754
  [nil, method, [], [], nil, false]
948
755
  in [:call, receiver, [:@period,] | [:@op, '&.',] | :'::' => dot, :call]
949
- [receiver, :call, [], [], nil, conditional[dot]]
756
+ [receiver, :call, [], [], nil, optional[dot]]
950
757
  in [:call, receiver, [:@period,] | [:@op, '&.',] | :'::' => dot, method]
951
758
  method => [:@ident | :@const | :@kw | :@op, method,] unless method == :call
952
- [receiver, method, [], [], nil, conditional[dot]]
759
+ [receiver, method, [], [], nil, optional[dot]]
953
760
  in [:command, [:@ident | :@const | :@kw | :@op, method,], args] # hoge 1, 2
954
761
  args, kwargs, block = retrieve_method_args args
955
762
  [nil, method, args, kwargs, block, false]
956
763
  in [:command_call, receiver, [:@period,] | [:@op, '&.',] | :'::' => dot, [:@ident | :@const | :@kw | :@op, method,], args] # a.hoge 1; a.hoge 1, 2;
957
764
  args, kwargs, block = retrieve_method_args args
958
- [receiver, method, args, kwargs, block, conditional[dot]]
765
+ [receiver, method, args, kwargs, block, optional[dot]]
959
766
  in [:method_add_arg, call, args]
960
- receiver, method, _arg, _kwarg, _block, cond = retrieve_method_call call
767
+ receiver, method, _arg, _kwarg, _block, opt = retrieve_method_call call
961
768
  args, kwargs, block = retrieve_method_args args
962
- [receiver, method, args, kwargs, block, cond]
769
+ [receiver, method, args, kwargs, block, opt]
963
770
  in [:method_add_block, call, block]
964
- receiver, method, args, kwargs, cond = retrieve_method_call call
965
- [receiver, method, args, kwargs, block, cond]
771
+ receiver, method, args, kwargs, opt = retrieve_method_call call
772
+ [receiver, method, args, kwargs, block, opt]
966
773
  end
967
774
  end
968
775
 
@@ -1031,16 +838,25 @@ class KatakataIrb::TypeSimulator
1031
838
  params_type = method.block.type.required_positionals.map do |func_param|
1032
839
  KatakataIrb::Types.from_rbs_type func_param.type, receiver, vars
1033
840
  end
1034
- block_response, breaks = block.call params_type
841
+ self_type = KatakataIrb::Types.from_rbs_type method.block.self_type, receiver, vars if method.block.self_type
842
+ block_response, breaks = block.call params_type, self_type
1035
843
  block_called = true
1036
844
  vars.merge! KatakataIrb::Types.match_free_variables(free_vars - vars.keys.to_set, [method.block.type.return_type], [block_response])
1037
845
  end
1038
846
  [KatakataIrb::Types.from_rbs_type(method.type.return_type, receiver, vars || {}), breaks]
1039
847
  end
1040
- block&.call [] unless block_called
848
+ block&.call [], nil unless block_called
1041
849
  types = type_breaks.map(&:first)
1042
850
  breaks = type_breaks.map(&:last).compact
1043
851
  types << OBJECT_METHODS[method_name.to_sym] if name_match && OBJECT_METHODS.has_key?(method_name.to_sym)
852
+
853
+ if method_name.to_sym == :new
854
+ receiver.types.each do |type|
855
+ if (type in KatakataIrb::Types::SingletonType) && type.module_or_class.is_a?(Class)
856
+ types << KatakataIrb::Types::InstanceType.new(type.module_or_class)
857
+ end
858
+ end
859
+ end
1044
860
  KatakataIrb::Types::UnionType[*types, *breaks]
1045
861
  end
1046
862
 
@@ -1148,7 +964,7 @@ class KatakataIrb::TypeSimulator
1148
964
  dig_targets = DigTarget.new(parents, target) do |_types, scope|
1149
965
  return scope
1150
966
  end
1151
- scope = Scope.from_binding(binding)
967
+ scope = KatakataIrb::Scope.from_binding(binding)
1152
968
  new(dig_targets).simulate_evaluate parents[0], scope
1153
969
  scope
1154
970
  end
@@ -1157,7 +973,7 @@ class KatakataIrb::TypeSimulator
1157
973
  dig_targets = DigTarget.new(parents, receiver) do |type, _scope|
1158
974
  return type
1159
975
  end
1160
- new(dig_targets).simulate_evaluate parents[0], Scope.from_binding(binding)
976
+ new(dig_targets).simulate_evaluate parents[0], KatakataIrb::Scope.from_binding(binding)
1161
977
  KatakataIrb::Types::NIL
1162
978
  end
1163
979
  end