katakata_irb 0.1.3 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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