typeprof 0.9.2 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -2
- data/lib/typeprof/analyzer.rb +82 -59
- data/lib/typeprof/block.rb +34 -0
- data/lib/typeprof/builtin.rb +169 -64
- data/lib/typeprof/cli.rb +2 -0
- data/lib/typeprof/config.rb +13 -1
- data/lib/typeprof/export.rb +114 -69
- data/lib/typeprof/import.rb +50 -28
- data/lib/typeprof/iseq.rb +23 -4
- data/lib/typeprof/method.rb +29 -7
- data/lib/typeprof/type.rb +41 -13
- data/lib/typeprof/version.rb +1 -1
- data/smoke/alias.rb +4 -4
- data/smoke/alias2.rb +3 -1
- data/smoke/arguments.rb +2 -2
- data/smoke/arguments2.rb +5 -5
- data/smoke/array-each.rb +1 -1
- data/smoke/array-each3.rb +1 -1
- data/smoke/array-map.rb +1 -1
- data/smoke/array-map2.rb +1 -1
- data/smoke/array-map3.rb +3 -3
- data/smoke/array-mul.rb +2 -2
- data/smoke/array-plus1.rb +1 -1
- data/smoke/array-plus2.rb +1 -0
- data/smoke/array-range-aref.rb +11 -11
- data/smoke/array-replace.rb +1 -1
- data/smoke/array1.rb +5 -5
- data/smoke/array10.rb +1 -1
- data/smoke/array11.rb +1 -1
- data/smoke/array12.rb +1 -1
- data/smoke/array14.rb +1 -1
- data/smoke/array15.rb +1 -1
- data/smoke/array2.rb +2 -2
- data/smoke/array3.rb +1 -0
- data/smoke/array6.rb +2 -1
- data/smoke/array8.rb +1 -1
- data/smoke/array9.rb +1 -1
- data/smoke/attr-module.rb +1 -0
- data/smoke/attr-vis.rb +43 -0
- data/smoke/attr-vis.rbs +4 -0
- data/smoke/attr.rb +2 -2
- data/smoke/block-ambiguous.rb +4 -4
- data/smoke/block-args1-rest.rb +6 -5
- data/smoke/block-args1.rb +5 -5
- data/smoke/block-args2-rest.rb +6 -5
- data/smoke/block-args2.rb +5 -5
- data/smoke/block-args3-rest.rb +7 -6
- data/smoke/block-args3.rb +6 -6
- data/smoke/block-blockarg.rb +3 -3
- data/smoke/block-kwarg.rb +4 -4
- data/smoke/block1.rb +1 -1
- data/smoke/block10.rb +1 -1
- data/smoke/block11.rb +2 -2
- data/smoke/block2.rb +1 -1
- data/smoke/block3.rb +1 -1
- data/smoke/block5.rb +1 -0
- data/smoke/block_given.rb +37 -0
- data/smoke/class_method.rb +2 -2
- data/smoke/class_method2.rb +2 -2
- data/smoke/constant2.rb +3 -2
- data/smoke/context-sensitive1.rb +1 -1
- data/smoke/cvar.rb +3 -2
- data/smoke/define_method.rb +2 -2
- data/smoke/define_method3.rb +1 -0
- data/smoke/define_method4.rb +1 -1
- data/smoke/define_method6.rb +19 -0
- data/smoke/demo.rb +6 -6
- data/smoke/demo1.rb +1 -1
- data/smoke/demo11.rb +1 -1
- data/smoke/demo2.rb +1 -1
- data/smoke/demo3.rb +1 -1
- data/smoke/demo4.rb +3 -3
- data/smoke/demo5.rb +1 -1
- data/smoke/demo6.rb +2 -1
- data/smoke/demo7.rb +1 -1
- data/smoke/demo9.rb +1 -0
- data/smoke/dummy-execution1.rb +1 -1
- data/smoke/dummy-execution2.rb +1 -1
- data/smoke/dummy_element.rb +1 -1
- data/smoke/ensure1.rb +1 -1
- data/smoke/enum_for.rb +15 -0
- data/smoke/enum_for2.rb +17 -0
- data/smoke/fib.rb +2 -2
- data/smoke/flow1.rb +1 -1
- data/smoke/flow10.rb +17 -0
- data/smoke/flow2.rb +1 -1
- data/smoke/flow3.rb +1 -1
- data/smoke/flow5.rb +1 -1
- data/smoke/flow6.rb +1 -1
- data/smoke/flow7.rb +1 -1
- data/smoke/flow8.rb +1 -1
- data/smoke/flow9.rb +1 -1
- data/smoke/function.rb +1 -1
- data/smoke/gvar.rb +1 -1
- data/smoke/gvar2.rb +1 -1
- data/smoke/hash-fetch.rb +3 -3
- data/smoke/inheritance.rb +4 -4
- data/smoke/initialize.rb +3 -2
- data/smoke/instance_eval.rb +1 -1
- data/smoke/int_times.rb +1 -1
- data/smoke/integer.rb +1 -1
- data/smoke/ivar.rb +3 -2
- data/smoke/ivar2.rb +2 -2
- data/smoke/ivar3.rb +2 -1
- data/smoke/ivar4.rb +1 -0
- data/smoke/kernel-class.rb +1 -1
- data/smoke/keyword4.rb +1 -1
- data/smoke/kwrest.rb +1 -0
- data/smoke/kwsplat1.rb +2 -2
- data/smoke/kwsplat2.rb +1 -1
- data/smoke/manual-rbs.rb +1 -0
- data/smoke/manual-rbs3.rb +1 -0
- data/smoke/method_missing.rb +4 -3
- data/smoke/module3.rb +1 -1
- data/smoke/module4.rb +1 -0
- data/smoke/module5.rb +1 -1
- data/smoke/module_function1.rb +3 -2
- data/smoke/module_function2.rb +3 -2
- data/smoke/multiple-include.rb +1 -0
- data/smoke/next1.rb +1 -1
- data/smoke/object-send1.rb +3 -3
- data/smoke/optional1.rb +1 -1
- data/smoke/optional2.rb +1 -1
- data/smoke/optional3.rb +1 -1
- data/smoke/parameterizedd-self.rb +2 -1
- data/smoke/prepend1.rb +33 -0
- data/smoke/prepend2.rb +10 -0
- data/smoke/prepend2.rbs +9 -0
- data/smoke/primitive_method.rb +19 -0
- data/smoke/proc4.rb +1 -1
- data/smoke/public.rb +4 -0
- data/smoke/range.rb +1 -1
- data/smoke/rbs-attr.rb +2 -2
- data/smoke/rbs-proc2.rb +1 -1
- data/smoke/rbs-proc3.rb +1 -1
- data/smoke/rbs-tyvar4.rb +3 -2
- data/smoke/rbs-tyvar6.rb +3 -3
- data/smoke/redo1.rb +1 -1
- data/smoke/redo2.rb +1 -1
- data/smoke/rescue1.rb +1 -1
- data/smoke/rescue2.rb +1 -1
- data/smoke/rescue3.rb +1 -0
- data/smoke/rescue4.rb +1 -1
- data/smoke/respond_to.rb +1 -1
- data/smoke/rest1.rb +2 -2
- data/smoke/rest2.rb +1 -1
- data/smoke/rest3.rb +6 -6
- data/smoke/rest4.rb +2 -2
- data/smoke/rest5.rb +1 -1
- data/smoke/rest6.rb +1 -1
- data/smoke/retry1.rb +2 -2
- data/smoke/simple.rb +1 -1
- data/smoke/step.rb +3 -3
- data/smoke/struct-keyword_init.rb +5 -15
- data/smoke/struct5.rb +1 -1
- data/smoke/struct6.rb +1 -1
- data/smoke/super1.rb +4 -4
- data/smoke/super3.rb +3 -2
- data/smoke/super4.rb +7 -5
- data/smoke/super5.rb +6 -4
- data/smoke/symbol-proc-attr.rb +1 -1
- data/smoke/tap1.rb +2 -2
- data/smoke/toplevel.rb +1 -1
- data/smoke/type_var.rb +3 -3
- data/smoke/user-demo.rb +1 -1
- data/smoke/wrong-extend.rb +1 -0
- data/smoke/wrong-include.rb +1 -0
- data/smoke/wrong-include2.rb +1 -1
- metadata +14 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8d68099e4f5d60a45f949d6bfc3a47e8b7d3b7ba66a0794f25f5fe61628de1d1
|
4
|
+
data.tar.gz: 22792d1acb9b16a4150f1afbaf29d59987bf29772908b23075e6668df81a4309
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 42faa4e3b5c64fd5976e66067bf13339c530785914caad77bc0a405939bc914e9adf78bfbd0aea57a829cb21aed3c6dfc09f8f57def85b09312facd82d33b5a9
|
7
|
+
data.tar.gz: bc6f115fbf1d5292286f04f09d745cfb0c13688a71fdae730d0cfdd903ad8f9f3f9019e532c37b4cf23fe41f39c9a1683f92f28af68716ddf7e625a0efca33f8
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
typeprof (0.
|
4
|
+
typeprof (0.10.0)
|
5
5
|
rbs (>= 0.20.1)
|
6
6
|
|
7
7
|
GEM
|
@@ -24,6 +24,7 @@ GEM
|
|
24
24
|
|
25
25
|
PLATFORMS
|
26
26
|
ruby
|
27
|
+
x86_64-linux
|
27
28
|
|
28
29
|
DEPENDENCIES
|
29
30
|
coverage-helpers
|
@@ -35,4 +36,4 @@ DEPENDENCIES
|
|
35
36
|
typeprof!
|
36
37
|
|
37
38
|
BUNDLED WITH
|
38
|
-
2.2.
|
39
|
+
2.2.1
|
data/lib/typeprof/analyzer.rb
CHANGED
@@ -117,30 +117,6 @@ module TypeProf
|
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
120
|
-
class TopStaticEnv
|
121
|
-
include Utils::StructuralEquality
|
122
|
-
|
123
|
-
def recv_ty
|
124
|
-
Type.bot
|
125
|
-
end
|
126
|
-
|
127
|
-
def blk_ty
|
128
|
-
Type.nil
|
129
|
-
end
|
130
|
-
|
131
|
-
def mod_func
|
132
|
-
false
|
133
|
-
end
|
134
|
-
|
135
|
-
def pub_meth
|
136
|
-
true
|
137
|
-
end
|
138
|
-
|
139
|
-
def merge(other)
|
140
|
-
raise unless other.is_a?(TopStaticEnv)
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
120
|
class Env
|
145
121
|
include Utils::StructuralEquality
|
146
122
|
|
@@ -246,6 +222,11 @@ module TypeProf
|
|
246
222
|
Env.new(senv, @locals, @stack, @type_params)
|
247
223
|
end
|
248
224
|
|
225
|
+
def replace_blk_ty(ty)
|
226
|
+
senv = StaticEnv.new(@static_env.recv_ty, ty, @static_env.mod_func, @static_env.pub_meth)
|
227
|
+
Env.new(senv, @locals, @stack, @type_params)
|
228
|
+
end
|
229
|
+
|
249
230
|
def inspect
|
250
231
|
"Env[#{ @static_env.inspect }, locals:#{ @locals.inspect }, stack:#{ @stack.inspect }, type_params:#{ (@type_params&.internal_hash).inspect }]"
|
251
232
|
end
|
@@ -319,7 +300,10 @@ module TypeProf
|
|
319
300
|
def initialize(kind, name, absolute_path)
|
320
301
|
raise unless name.is_a?(Array)
|
321
302
|
@kind = kind
|
322
|
-
@modules = {
|
303
|
+
@modules = {
|
304
|
+
:before => { true => [], false => [] }, # before = include/extend
|
305
|
+
:after => { true => [], false => [] }, # after = prepend
|
306
|
+
}
|
323
307
|
@name = name
|
324
308
|
@consts = {}
|
325
309
|
@methods = {}
|
@@ -332,13 +316,13 @@ module TypeProf
|
|
332
316
|
attr_reader :kind, :modules, :consts, :methods, :ivars, :cvars, :absolute_path
|
333
317
|
attr_accessor :name, :klass_obj
|
334
318
|
|
335
|
-
def
|
336
|
-
mod_, module_type_args, absolute_paths = @modules[singleton].find {|m,| m == mod }
|
319
|
+
def mix_module(kind, mod, type_args, singleton, absolute_path)
|
320
|
+
mod_, module_type_args, absolute_paths = @modules[kind][singleton].find {|m,| m == mod }
|
337
321
|
if mod_
|
338
|
-
raise "inconsistent include/extend type args in RBS?" if module_type_args != type_args && type_args != [] && type_args != nil
|
322
|
+
raise "inconsistent #{ kind == :after ? "include/extend" : "prepend" } type args in RBS?" if module_type_args != type_args && type_args != [] && type_args != nil
|
339
323
|
else
|
340
324
|
absolute_paths = Utils::MutableSet.new
|
341
|
-
@modules[singleton].unshift([mod, type_args, absolute_paths])
|
325
|
+
@modules[kind][singleton].unshift([mod, type_args, absolute_paths])
|
342
326
|
end
|
343
327
|
absolute_paths << absolute_path
|
344
328
|
end
|
@@ -355,10 +339,8 @@ module TypeProf
|
|
355
339
|
@consts[name] = [ty, absolute_path]
|
356
340
|
end
|
357
341
|
|
358
|
-
def
|
359
|
-
|
360
|
-
yield subst, direct if mthds&.include?(mthd)
|
361
|
-
@modules[singleton].each do |mod_def, type_args,|
|
342
|
+
def adjust_substitution_for_module(mods, mid, mthd, subst, &blk)
|
343
|
+
mods.each do |mod_def, type_args,|
|
362
344
|
if mod_def.klass_obj.type_params && type_args
|
363
345
|
subst2 = {}
|
364
346
|
mod_def.klass_obj.type_params.zip(type_args) do |(tyvar, *), tyarg|
|
@@ -370,13 +352,28 @@ module TypeProf
|
|
370
352
|
end
|
371
353
|
end
|
372
354
|
|
355
|
+
def adjust_substitution(singleton, mid, mthd, subst, direct, &blk)
|
356
|
+
adjust_substitution_for_module(@modules[:before][singleton], mid, mthd, subst, &blk)
|
357
|
+
|
358
|
+
mthds = @methods[[singleton, mid]]
|
359
|
+
yield subst, direct if mthds&.include?(mthd)
|
360
|
+
|
361
|
+
adjust_substitution_for_module(@modules[:after][singleton], mid, mthd, subst, &blk)
|
362
|
+
end
|
363
|
+
|
373
364
|
def search_method(singleton, mid, visited, &blk)
|
374
365
|
# Currently, circular inclusion of modules is allowed
|
375
366
|
return if visited[self]
|
376
367
|
visited[self] = true
|
368
|
+
|
369
|
+
@modules[:before][singleton].each do |mod_def,|
|
370
|
+
mod_def.search_method(false, mid, visited, &blk)
|
371
|
+
end
|
372
|
+
|
377
373
|
mthds = @methods[[singleton, mid]]
|
378
374
|
yield mthds, @klass_obj, singleton if mthds
|
379
|
-
|
375
|
+
|
376
|
+
@modules[:after][singleton].each do |mod_def,|
|
380
377
|
mod_def.search_method(false, mid, visited, &blk)
|
381
378
|
end
|
382
379
|
end
|
@@ -405,17 +402,17 @@ module TypeProf
|
|
405
402
|
end
|
406
403
|
end
|
407
404
|
|
408
|
-
def
|
409
|
-
return if
|
405
|
+
def mix_module(kind, mixing_mod, mixed_mod, type_args, singleton, caller_ep)
|
406
|
+
return if mixed_mod == Type.any
|
410
407
|
|
411
|
-
|
412
|
-
|
413
|
-
if
|
414
|
-
|
415
|
-
if
|
416
|
-
|
408
|
+
mixing_mod = @class_defs[mixing_mod.idx]
|
409
|
+
mixed_mod.each_child do |mixed_mod|
|
410
|
+
if mixed_mod.is_a?(Type::Class)
|
411
|
+
mixed_mod = @class_defs[mixed_mod.idx]
|
412
|
+
if mixed_mod && mixed_mod.kind == :module
|
413
|
+
mixing_mod.mix_module(kind, mixed_mod, type_args, singleton, caller_ep ? caller_ep.ctx.iseq.absolute_path : nil)
|
417
414
|
else
|
418
|
-
warn(caller_ep, "
|
415
|
+
warn(caller_ep, "attempted to #{ kind == :after ? "include/extend" : "prepend" } non-module; ignored")
|
419
416
|
end
|
420
417
|
end
|
421
418
|
end
|
@@ -602,12 +599,12 @@ module TypeProf
|
|
602
599
|
mdef
|
603
600
|
end
|
604
601
|
|
605
|
-
def add_attr_method(klass,
|
602
|
+
def add_attr_method(klass, mid, ivar, kind, pub_meth, ep)
|
606
603
|
if kind == :reader || kind == :accessor
|
607
|
-
add_method(klass, mid, false, AttrMethodDef.new(ivar, :reader,
|
604
|
+
add_method(klass, mid, false, AttrMethodDef.new(ivar, :reader, pub_meth, ep))
|
608
605
|
end
|
609
606
|
if kind == :writer || kind == :accessor
|
610
|
-
add_method(klass, :"#{ mid }=", false, AttrMethodDef.new(ivar, :writer,
|
607
|
+
add_method(klass, :"#{ mid }=", false, AttrMethodDef.new(ivar, :writer, pub_meth, ep))
|
611
608
|
end
|
612
609
|
end
|
613
610
|
|
@@ -619,22 +616,22 @@ module TypeProf
|
|
619
616
|
add_method(klass, mid, true, ISeqMethodDef.new(iseq, cref, outer_ep, pub_meth))
|
620
617
|
end
|
621
618
|
|
622
|
-
def set_custom_method(klass, mid, impl)
|
623
|
-
set_method(klass, mid, false, CustomMethodDef.new(impl))
|
619
|
+
def set_custom_method(klass, mid, impl, pub_meth = true)
|
620
|
+
set_method(klass, mid, false, CustomMethodDef.new(impl, pub_meth))
|
624
621
|
end
|
625
622
|
|
626
|
-
def set_singleton_custom_method(klass, mid, impl)
|
627
|
-
set_method(klass, mid, true, CustomMethodDef.new(impl))
|
623
|
+
def set_singleton_custom_method(klass, mid, impl, pub_meth = true)
|
624
|
+
set_method(klass, mid, true, CustomMethodDef.new(impl, pub_meth))
|
628
625
|
end
|
629
626
|
|
630
|
-
def alias_method(klass, singleton,
|
627
|
+
def alias_method(klass, singleton, alias_mid, orig_mid, ep)
|
631
628
|
if klass == Type.any
|
632
629
|
self
|
633
630
|
else
|
634
|
-
mdefs = get_method(klass, singleton,
|
631
|
+
mdefs = get_method(klass, singleton, orig_mid)
|
635
632
|
if mdefs
|
636
633
|
mdefs.each do |mdef|
|
637
|
-
@class_defs[klass.idx].add_method(
|
634
|
+
@class_defs[klass.idx].add_method(alias_mid, singleton, AliasMethodDef.new(orig_mid, mdef, ep))
|
638
635
|
end
|
639
636
|
end
|
640
637
|
end
|
@@ -723,7 +720,7 @@ module TypeProf
|
|
723
720
|
if ep
|
724
721
|
if entry.rbs_declared
|
725
722
|
unless Type.match?(ty, entry.type)
|
726
|
-
scratch.warn(ep, "inconsistent assignment to RBS-declared
|
723
|
+
scratch.warn(ep, "inconsistent assignment to RBS-declared variable")
|
727
724
|
return
|
728
725
|
end
|
729
726
|
end
|
@@ -1076,7 +1073,7 @@ module TypeProf
|
|
1076
1073
|
lead_tys = env.locals[0, lead_num].map {|ty| globalize_type(ty, env, ep) }
|
1077
1074
|
opt_tys = opt.size > 1 ? env.locals[lead_num, opt.size - 1].map {|ty| globalize_type(ty, env, ep) } : []
|
1078
1075
|
if rest_start # XXX:squash
|
1079
|
-
ty = globalize_type(env.locals[
|
1076
|
+
ty = globalize_type(env.locals[rest_start], env, ep)
|
1080
1077
|
rest_ty = Type.bot
|
1081
1078
|
ty.each_child_global do |ty|
|
1082
1079
|
if ty.is_a?(Type::Array)
|
@@ -1111,6 +1108,7 @@ module TypeProf
|
|
1111
1108
|
end
|
1112
1109
|
end
|
1113
1110
|
kw_rest_ty = globalize_type(env.locals[kw_rest], env, ep) if kw_rest
|
1111
|
+
kw_rest_ty = nil if kw_rest_ty == Type.nil
|
1114
1112
|
if block_start
|
1115
1113
|
blk_ty = globalize_type(env.locals[block_start], env, ep)
|
1116
1114
|
elsif iseq.type == :method
|
@@ -1290,7 +1288,7 @@ module TypeProf
|
|
1290
1288
|
end
|
1291
1289
|
end
|
1292
1290
|
return
|
1293
|
-
when :
|
1291
|
+
when :getlocal_send_branch
|
1294
1292
|
getlocal_operands, send_operands, branch_operands = operands
|
1295
1293
|
env, recvs, mid, aargs = setup_actual_arguments(:method, send_operands, ep, env)
|
1296
1294
|
recvs = Type.any if recvs == Type.bot
|
@@ -1318,6 +1316,31 @@ module TypeProf
|
|
1318
1316
|
end
|
1319
1317
|
end
|
1320
1318
|
return
|
1319
|
+
when :send_branch
|
1320
|
+
send_operands, branch_operands = operands
|
1321
|
+
env, recvs, mid, aargs = setup_actual_arguments(:method, send_operands, ep, env)
|
1322
|
+
recvs = Type.any if recvs == Type.bot
|
1323
|
+
recvs.each_child do |recv|
|
1324
|
+
do_send(recv, mid, aargs, ep, env) do |ret_ty, ep, env|
|
1325
|
+
env, ret_ty, = localize_type(ret_ty, env, ep)
|
1326
|
+
|
1327
|
+
branchtype, target, = branch_operands
|
1328
|
+
# branchtype: :if or :unless or :nil
|
1329
|
+
ep_then = ep.next
|
1330
|
+
ep_else = ep.jump(target)
|
1331
|
+
|
1332
|
+
case ret_ty
|
1333
|
+
when Type::Instance.new(Type::Builtin[:true])
|
1334
|
+
merge_env(branchtype == :if ? ep_else : ep_then, env)
|
1335
|
+
when Type::Instance.new(Type::Builtin[:false])
|
1336
|
+
merge_env(branchtype == :if ? ep_then : ep_else, env)
|
1337
|
+
else
|
1338
|
+
merge_env(ep_then, env)
|
1339
|
+
merge_env(ep_else, env)
|
1340
|
+
end
|
1341
|
+
end
|
1342
|
+
end
|
1343
|
+
return
|
1321
1344
|
when :invokeblock
|
1322
1345
|
env, recvs, mid, aargs = setup_actual_arguments(:block, operands, ep, env)
|
1323
1346
|
blk = env.static_env.blk_ty
|
@@ -2130,7 +2153,7 @@ module TypeProf
|
|
2130
2153
|
|
2131
2154
|
bsig ||= BlockSignature.new([], [], nil, Type.nil)
|
2132
2155
|
|
2133
|
-
bsig = bsig.screen_name(self)
|
2156
|
+
bsig = bsig.screen_name(nil, self)
|
2134
2157
|
ret_ty = ret_ty.screen_name(self)
|
2135
2158
|
ret_ty = (ret_ty.include?("|") ? "(#{ ret_ty })" : ret_ty) # XXX?
|
2136
2159
|
|
@@ -2157,7 +2180,7 @@ module TypeProf
|
|
2157
2180
|
end
|
2158
2181
|
end
|
2159
2182
|
|
2160
|
-
farg_tys = farg_tys ? farg_tys.screen_name(self) : "(unknown)"
|
2183
|
+
farg_tys = farg_tys ? farg_tys.screen_name(nil, self) : "(unknown)"
|
2161
2184
|
ret_ty = ret_ty.screen_name(self)
|
2162
2185
|
ret_ty = (ret_ty.include?("|") ? "(#{ ret_ty })" : ret_ty) # XXX?
|
2163
2186
|
|
@@ -2169,7 +2192,7 @@ module TypeProf
|
|
2169
2192
|
farg_tys = @method_signatures[ctx]
|
2170
2193
|
ret_ty = @return_values[ctx] || Type.bot
|
2171
2194
|
|
2172
|
-
farg_tys = farg_tys.screen_name(self)
|
2195
|
+
farg_tys = farg_tys.screen_name(ctx.iseq, self)
|
2173
2196
|
ret_ty = ret_ty.screen_name(self)
|
2174
2197
|
ret_ty = (ret_ty.include?("|") ? "(#{ ret_ty })" : ret_ty) # XXX?
|
2175
2198
|
"#{ (farg_tys.empty? ? "" : "#{ farg_tys } ") }-> #{ ret_ty }"
|
data/lib/typeprof/block.rb
CHANGED
@@ -137,4 +137,38 @@ module TypeProf
|
|
137
137
|
end
|
138
138
|
end
|
139
139
|
end
|
140
|
+
|
141
|
+
class CustomBlock < Block
|
142
|
+
def initialize(caller_ep, mid, &blk)
|
143
|
+
@caller_ep = caller_ep
|
144
|
+
@mid = mid
|
145
|
+
@blk = blk
|
146
|
+
end
|
147
|
+
|
148
|
+
def inspect
|
149
|
+
"#<CustomBlock>"
|
150
|
+
end
|
151
|
+
|
152
|
+
def consistent?(other)
|
153
|
+
true # XXX
|
154
|
+
end
|
155
|
+
|
156
|
+
def substitute(_subst, _depth)
|
157
|
+
self
|
158
|
+
end
|
159
|
+
|
160
|
+
def do_call(aargs, caller_ep, caller_env, scratch, replace_recv_ty:, &ctn)
|
161
|
+
aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
|
162
|
+
|
163
|
+
dummy_ctx = TypedContext.new(@caller_ep, @mid)
|
164
|
+
|
165
|
+
scratch.add_block_signature!(self, aargs.to_block_signature)
|
166
|
+
scratch.add_block_to_ctx!(self, dummy_ctx)
|
167
|
+
|
168
|
+
@blk.call(aargs, caller_ep, caller_env, scratch, replace_recv_ty: replace_recv_ty) do |ret_ty, ep, env|
|
169
|
+
scratch.add_return_value!(dummy_ctx, ret_ty)
|
170
|
+
ctn[ret_ty, ep, env]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
140
174
|
end
|
data/lib/typeprof/builtin.rb
CHANGED
@@ -19,7 +19,7 @@ module TypeProf
|
|
19
19
|
klass, new_mid, old_mid = aargs.lead_tys
|
20
20
|
new_sym = get_sym("alias", new_mid, ep, scratch) or return
|
21
21
|
old_sym = get_sym("alias", old_mid, ep, scratch) or return
|
22
|
-
scratch.alias_method(klass, ep.ctx.cref.singleton, new_sym, old_sym)
|
22
|
+
scratch.alias_method(klass, ep.ctx.cref.singleton, new_sym, old_sym, ep)
|
23
23
|
ctn[Type.nil, ep, env]
|
24
24
|
end
|
25
25
|
|
@@ -163,6 +163,66 @@ module TypeProf
|
|
163
163
|
end
|
164
164
|
end
|
165
165
|
|
166
|
+
def object_enum_for(recv, mid, aargs, ep, env, scratch, &ctn)
|
167
|
+
if aargs.lead_tys.size >= 1
|
168
|
+
mid_ty, = aargs.lead_tys
|
169
|
+
naargs = ActualArguments.new(aargs.lead_tys[1..], aargs.rest_ty, aargs.kw_tys, aargs.blk_ty)
|
170
|
+
elsif aargs.rest_ty
|
171
|
+
mid_ty = aargs.rest_ty
|
172
|
+
naargs = aargs
|
173
|
+
else
|
174
|
+
mid_ty = Type::Symbol.new(:each, Type::Instance.new(Type::Builtin[:sym]))
|
175
|
+
naargs = aargs
|
176
|
+
end
|
177
|
+
|
178
|
+
elem_ty = Type.bot
|
179
|
+
enum_for_blk = CustomBlock.new(ep, mid) do |aargs, caller_ep, caller_env, scratch, replace_recv_ty:, &blk_ctn|
|
180
|
+
if aargs.lead_tys.size >= 1
|
181
|
+
elem_ty = elem_ty.union(aargs.lead_tys[0])
|
182
|
+
else
|
183
|
+
elem_ty = elem_ty.union(Type.any)
|
184
|
+
end
|
185
|
+
ctn[Type::Cell.new(Type::Cell::Elements.new([elem_ty, Type.any]), Type::Instance.new(Type::Builtin[:enumerator])), ep, env]
|
186
|
+
blk_ctn[Type.any, caller_ep, caller_env]
|
187
|
+
end
|
188
|
+
enum_for_blk_ty = Type::Proc.new(enum_for_blk, Type::Instance.new(Type::Builtin[:proc]))
|
189
|
+
|
190
|
+
naargs = ActualArguments.new(naargs.lead_tys, naargs.rest_ty, naargs.kw_tys, enum_for_blk_ty)
|
191
|
+
mid_ty.each_child do |mid|
|
192
|
+
if mid.is_a?(Type::Symbol)
|
193
|
+
mid = mid.sym
|
194
|
+
scratch.do_send(recv, mid, naargs, ep, env) do |_ret_ty, _ep|
|
195
|
+
ctn[Type::Cell.new(Type::Cell::Elements.new([elem_ty, Type.any]), Type::Instance.new(Type::Builtin[:enumerator])), ep, env]
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def object_privitive_method(recv, mid, aargs, ep, env, scratch, &ctn)
|
202
|
+
ctn[Type::Symbol.new(ep.ctx.mid, Type::Instance.new(Type::Builtin[:sym])), ep, env]
|
203
|
+
end
|
204
|
+
|
205
|
+
def object_block_given?(recv, mid, aargs, ep, env, scratch, &ctn)
|
206
|
+
procs = Type.bot
|
207
|
+
no_proc = false
|
208
|
+
env.static_env.blk_ty.each_child do |blk_ty|
|
209
|
+
case blk_ty
|
210
|
+
when Type::Proc
|
211
|
+
procs = procs.union(blk_ty)
|
212
|
+
when Type.nil
|
213
|
+
no_proc = true
|
214
|
+
else
|
215
|
+
ctn[Type.bool, ep, env]
|
216
|
+
end
|
217
|
+
end
|
218
|
+
if procs != Type.bot
|
219
|
+
ctn[Type::Instance.new(Type::Builtin[:true]), ep, env.replace_blk_ty(procs)]
|
220
|
+
end
|
221
|
+
if no_proc
|
222
|
+
ctn[Type::Instance.new(Type::Builtin[:false]), ep, env.replace_blk_ty(Type.nil)]
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
166
226
|
def module_include(recv, mid, aargs, ep, env, scratch, &ctn)
|
167
227
|
if aargs.lead_tys.size != 1
|
168
228
|
scratch.warn(ep, "Module#include without an argument is ignored")
|
@@ -178,7 +238,7 @@ module TypeProf
|
|
178
238
|
arg = aargs.lead_tys[0]
|
179
239
|
arg.each_child do |arg|
|
180
240
|
if arg.is_a?(Type::Class)
|
181
|
-
scratch.
|
241
|
+
scratch.mix_module(:after, recv, arg, nil, ep.ctx.cref.singleton, ep)
|
182
242
|
end
|
183
243
|
end
|
184
244
|
ctn[recv, ep, env]
|
@@ -199,7 +259,29 @@ module TypeProf
|
|
199
259
|
arg = aargs.lead_tys[0]
|
200
260
|
arg.each_child do |arg|
|
201
261
|
if arg.is_a?(Type::Class)
|
202
|
-
|
262
|
+
# if ep.ctx.cref.singleton is true, the meta-meta level is ignored. Should we warn?
|
263
|
+
scratch.mix_module(:after, recv, arg, nil, true, ep)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
ctn[recv, ep, env]
|
267
|
+
end
|
268
|
+
|
269
|
+
def module_prepend(recv, mid, aargs, ep, env, scratch, &ctn)
|
270
|
+
if aargs.lead_tys.size != 1
|
271
|
+
scratch.warn(ep, "Module#prepend without an argument is ignored")
|
272
|
+
ctn[Type.any, ep, env]
|
273
|
+
return
|
274
|
+
end
|
275
|
+
|
276
|
+
unless recv.is_a?(Type::Class)
|
277
|
+
# XXX: warn?
|
278
|
+
return ctn[Type.any, ep, env]
|
279
|
+
end
|
280
|
+
|
281
|
+
arg = aargs.lead_tys[0]
|
282
|
+
arg.each_child do |arg|
|
283
|
+
if arg.is_a?(Type::Class)
|
284
|
+
scratch.mix_module(:before, recv, arg, nil, ep.ctx.cref.singleton, ep)
|
203
285
|
end
|
204
286
|
end
|
205
287
|
ctn[recv, ep, env]
|
@@ -268,23 +350,25 @@ module TypeProf
|
|
268
350
|
end
|
269
351
|
|
270
352
|
mid, = aargs.lead_tys
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
353
|
+
mid.each_child do |mid|
|
354
|
+
if mid.is_a?(Type::Symbol)
|
355
|
+
mid = mid.sym
|
356
|
+
aargs.blk_ty.each_child do |blk_ty|
|
357
|
+
if blk_ty.is_a?(Type::Proc)
|
358
|
+
blk = blk_ty.block_body
|
359
|
+
case blk
|
360
|
+
when ISeqBlock
|
361
|
+
scratch.do_define_iseq_method(ep, env, mid, blk.iseq, blk.outer_ep)
|
362
|
+
else
|
363
|
+
# XXX: what to do?
|
364
|
+
end
|
279
365
|
else
|
280
366
|
# XXX: what to do?
|
281
367
|
end
|
282
|
-
else
|
283
|
-
# XXX: what to do?
|
284
368
|
end
|
369
|
+
else
|
370
|
+
# XXX: what to do?
|
285
371
|
end
|
286
|
-
else
|
287
|
-
# XXX: what to do?
|
288
372
|
end
|
289
373
|
ctn[Type.any, ep, env]
|
290
374
|
end
|
@@ -293,7 +377,7 @@ module TypeProf
|
|
293
377
|
aargs.lead_tys.each do |aarg|
|
294
378
|
sym = get_sym("attr_accessor", aarg, ep, scratch) or next
|
295
379
|
cref = ep.ctx.cref
|
296
|
-
scratch.add_attr_method(cref.klass,
|
380
|
+
scratch.add_attr_method(cref.klass, sym, :"@#{ sym }", :accessor, env.static_env.pub_meth, ep)
|
297
381
|
end
|
298
382
|
ctn[Type.nil, ep, env]
|
299
383
|
end
|
@@ -302,7 +386,7 @@ module TypeProf
|
|
302
386
|
aargs.lead_tys.each do |aarg|
|
303
387
|
sym = get_sym("attr_reader", aarg, ep, scratch) or next
|
304
388
|
cref = ep.ctx.cref
|
305
|
-
scratch.add_attr_method(cref.klass,
|
389
|
+
scratch.add_attr_method(cref.klass, sym, :"@#{ sym }", :reader, env.static_env.pub_meth, ep)
|
306
390
|
end
|
307
391
|
ctn[Type.nil, ep, env]
|
308
392
|
end
|
@@ -311,7 +395,7 @@ module TypeProf
|
|
311
395
|
aargs.lead_tys.each do |aarg|
|
312
396
|
sym = get_sym("attr_writer", aarg, ep, scratch) or next
|
313
397
|
cref = ep.ctx.cref
|
314
|
-
scratch.add_attr_method(cref.klass,
|
398
|
+
scratch.add_attr_method(cref.klass, sym, :"@#{ sym }", :writer, env.static_env.pub_meth, ep)
|
315
399
|
end
|
316
400
|
ctn[Type.nil, ep, env]
|
317
401
|
end
|
@@ -444,43 +528,57 @@ module TypeProf
|
|
444
528
|
ctn[Type.any, ep, env]
|
445
529
|
return
|
446
530
|
end
|
447
|
-
scratch.add_ivar_read!(Type::Instance.new(struct_klass), :
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
531
|
+
scratch.add_ivar_read!(Type::Instance.new(struct_klass), :_keyword_init, ep) do |keyword_init, ep|
|
532
|
+
scratch.add_ivar_read!(Type::Instance.new(struct_klass), :_members, ep) do |member_ary_ty, ep|
|
533
|
+
next if member_ary_ty == Type.nil
|
534
|
+
if keyword_init == Type::Instance.new(Type::Builtin[:true])
|
535
|
+
# TODO: support kw_rest_ty
|
536
|
+
aargs.kw_tys.each do |key, val_ty|
|
537
|
+
found = false
|
538
|
+
member_ary_ty.elems.lead_tys.each do |sym|
|
539
|
+
if sym.sym == key
|
540
|
+
found = true
|
541
|
+
scratch.set_instance_variable(recv, sym.sym, val_ty, ep, env)
|
542
|
+
end
|
543
|
+
end
|
544
|
+
unless found
|
545
|
+
# TODO: what to do when not found?
|
546
|
+
end
|
547
|
+
end
|
548
|
+
else
|
549
|
+
member_ary_ty.elems.lead_tys.zip(aargs.lead_tys) do |sym, ty|
|
550
|
+
ty ||= Type.nil
|
551
|
+
scratch.set_instance_variable(recv, sym.sym, ty, ep, env)
|
552
|
+
end
|
553
|
+
end
|
452
554
|
end
|
453
555
|
end
|
454
556
|
ctn[recv, ep, env]
|
455
557
|
end
|
456
558
|
|
457
|
-
def
|
559
|
+
def struct_s_new(recv, mid, aargs, ep, env, scratch, &ctn)
|
458
560
|
# TODO: keyword_init
|
459
561
|
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
ctn[recv, ep, env]
|
562
|
+
keyword_init = false
|
563
|
+
if aargs.kw_tys && aargs.kw_tys[:keyword_init] # XXX: more canonical way to extract keyword...
|
564
|
+
if aargs.kw_tys[:keyword_init] == Type::Instance.new(Type::Builtin[:true])
|
565
|
+
keyword_init = true
|
465
566
|
end
|
466
567
|
end
|
467
|
-
end
|
468
|
-
|
469
|
-
def struct_s_new(recv, mid, aargs, ep, env, scratch, &ctn)
|
470
|
-
# TODO: keyword_init
|
471
568
|
|
472
569
|
fields = aargs.lead_tys.map {|ty| get_sym("Struct.new", ty, ep, scratch) }.compact
|
473
570
|
struct_klass = scratch.new_struct(ep)
|
474
571
|
|
475
|
-
scratch.set_singleton_custom_method(struct_klass, :new, Builtin.method(:
|
476
|
-
scratch.set_singleton_custom_method(struct_klass, :[], Builtin.method(:
|
572
|
+
scratch.set_singleton_custom_method(struct_klass, :new, Builtin.method(:object_s_new))
|
573
|
+
scratch.set_singleton_custom_method(struct_klass, :[], Builtin.method(:object_s_new))
|
477
574
|
fields.each do |field|
|
478
|
-
scratch.add_attr_method(struct_klass,
|
575
|
+
scratch.add_attr_method(struct_klass, field, field, :accessor, true, ep)
|
479
576
|
end
|
480
577
|
fields = fields.map {|field| Type::Symbol.new(field, Type::Instance.new(Type::Builtin[:sym])) }
|
481
578
|
base_ty = Type::Instance.new(Type::Builtin[:ary])
|
482
579
|
fields = Type::Array.new(Type::Array::Elements.new(fields), base_ty)
|
483
580
|
scratch.add_ivar_write!(Type::Instance.new(struct_klass), :_members, fields, ep)
|
581
|
+
scratch.add_ivar_write!(Type::Instance.new(struct_klass), :_keyword_init, Type::Instance.new(Type::Builtin[:true]), ep) if keyword_init
|
484
582
|
#set_singleton_custom_method(struct_klass, :members, Builtin.method(:...))
|
485
583
|
|
486
584
|
ctn[struct_klass, ep, env]
|
@@ -654,25 +752,26 @@ module TypeProf
|
|
654
752
|
|
655
753
|
Import.import_builtin(scratch)
|
656
754
|
|
657
|
-
Type::Builtin[:vmcore]
|
658
|
-
Type::Builtin[:int]
|
659
|
-
Type::Builtin[:float]
|
660
|
-
Type::Builtin[:rational]
|
661
|
-
Type::Builtin[:complex]
|
662
|
-
Type::Builtin[:sym]
|
663
|
-
Type::Builtin[:str]
|
664
|
-
Type::Builtin[:struct]
|
665
|
-
Type::Builtin[:ary]
|
666
|
-
Type::Builtin[:hash]
|
667
|
-
Type::Builtin[:io]
|
668
|
-
Type::Builtin[:proc]
|
669
|
-
Type::Builtin[:range]
|
670
|
-
Type::Builtin[:regexp]
|
671
|
-
Type::Builtin[:matchdata]
|
672
|
-
Type::Builtin[:class]
|
673
|
-
Type::Builtin[:module]
|
674
|
-
Type::Builtin[:exc]
|
675
|
-
Type::Builtin[:encoding]
|
755
|
+
Type::Builtin[:vmcore] = scratch.new_class(klass_obj, :VMCore, [], klass_obj, nil)
|
756
|
+
Type::Builtin[:int] = scratch.get_constant(klass_obj, :Integer)
|
757
|
+
Type::Builtin[:float] = scratch.get_constant(klass_obj, :Float)
|
758
|
+
Type::Builtin[:rational] = scratch.get_constant(klass_obj, :Rational)
|
759
|
+
Type::Builtin[:complex] = scratch.get_constant(klass_obj, :Complex)
|
760
|
+
Type::Builtin[:sym] = scratch.get_constant(klass_obj, :Symbol)
|
761
|
+
Type::Builtin[:str] = scratch.get_constant(klass_obj, :String)
|
762
|
+
Type::Builtin[:struct] = scratch.get_constant(klass_obj, :Struct)
|
763
|
+
Type::Builtin[:ary] = scratch.get_constant(klass_obj, :Array)
|
764
|
+
Type::Builtin[:hash] = scratch.get_constant(klass_obj, :Hash)
|
765
|
+
Type::Builtin[:io] = scratch.get_constant(klass_obj, :IO)
|
766
|
+
Type::Builtin[:proc] = scratch.get_constant(klass_obj, :Proc)
|
767
|
+
Type::Builtin[:range] = scratch.get_constant(klass_obj, :Range)
|
768
|
+
Type::Builtin[:regexp] = scratch.get_constant(klass_obj, :Regexp)
|
769
|
+
Type::Builtin[:matchdata] = scratch.get_constant(klass_obj, :MatchData)
|
770
|
+
Type::Builtin[:class] = scratch.get_constant(klass_obj, :Class)
|
771
|
+
Type::Builtin[:module] = scratch.get_constant(klass_obj, :Module)
|
772
|
+
Type::Builtin[:exc] = scratch.get_constant(klass_obj, :Exception)
|
773
|
+
Type::Builtin[:encoding] = scratch.get_constant(klass_obj, :Encoding)
|
774
|
+
Type::Builtin[:enumerator] = scratch.get_constant(klass_obj, :Enumerator)
|
676
775
|
|
677
776
|
klass_vmcore = Type::Builtin[:vmcore]
|
678
777
|
klass_ary = Type::Builtin[:ary]
|
@@ -687,19 +786,25 @@ module TypeProf
|
|
687
786
|
scratch.set_custom_method(klass_vmcore, :"core#raise", Builtin.method(:vmcore_raise))
|
688
787
|
scratch.set_custom_method(klass_vmcore, :lambda, Builtin.method(:lambda))
|
689
788
|
scratch.set_singleton_custom_method(klass_obj, :"new", Builtin.method(:object_s_new))
|
690
|
-
scratch.set_custom_method(klass_obj, :p, Builtin.method(:kernel_p))
|
789
|
+
scratch.set_custom_method(klass_obj, :p, Builtin.method(:kernel_p), false)
|
691
790
|
scratch.set_custom_method(klass_obj, :is_a?, Builtin.method(:object_is_a?))
|
692
791
|
scratch.set_custom_method(klass_obj, :respond_to?, Builtin.method(:object_respond_to?))
|
693
792
|
scratch.set_custom_method(klass_obj, :class, Builtin.method(:object_class))
|
694
793
|
scratch.set_custom_method(klass_obj, :send, Builtin.method(:object_send))
|
695
794
|
scratch.set_custom_method(klass_obj, :instance_eval, Builtin.method(:object_instance_eval))
|
696
|
-
scratch.set_custom_method(klass_obj, :proc, Builtin.method(:lambda))
|
795
|
+
scratch.set_custom_method(klass_obj, :proc, Builtin.method(:lambda), false)
|
796
|
+
scratch.set_custom_method(klass_obj, :__method__, Builtin.method(:object_privitive_method), false)
|
797
|
+
scratch.set_custom_method(klass_obj, :block_given?, Builtin.method(:object_block_given?), false)
|
798
|
+
|
799
|
+
scratch.set_custom_method(klass_obj, :enum_for, Builtin.method(:object_enum_for))
|
800
|
+
scratch.set_custom_method(klass_obj, :to_enum, Builtin.method(:object_enum_for))
|
697
801
|
|
698
802
|
scratch.set_custom_method(klass_module, :include, Builtin.method(:module_include))
|
699
803
|
scratch.set_custom_method(klass_module, :extend, Builtin.method(:module_extend))
|
700
|
-
scratch.set_custom_method(klass_module, :
|
701
|
-
scratch.set_custom_method(klass_module, :
|
702
|
-
scratch.set_custom_method(klass_module, :
|
804
|
+
scratch.set_custom_method(klass_module, :prepend, Builtin.method(:module_prepend))
|
805
|
+
scratch.set_custom_method(klass_module, :module_function, Builtin.method(:module_module_function), false)
|
806
|
+
scratch.set_custom_method(klass_module, :public, Builtin.method(:module_public), false)
|
807
|
+
scratch.set_custom_method(klass_module, :private, Builtin.method(:module_private), false)
|
703
808
|
scratch.set_custom_method(klass_module, :define_method, Builtin.method(:module_define_method))
|
704
809
|
scratch.set_custom_method(klass_module, :"attr_accessor", Builtin.method(:module_attr_accessor))
|
705
810
|
scratch.set_custom_method(klass_module, :"attr_reader", Builtin.method(:module_attr_reader))
|
@@ -718,10 +823,10 @@ module TypeProf
|
|
718
823
|
scratch.set_custom_method(klass_struct, :initialize, Builtin.method(:struct_initialize))
|
719
824
|
scratch.set_singleton_custom_method(klass_struct, :new, Builtin.method(:struct_s_new))
|
720
825
|
|
721
|
-
scratch.set_custom_method(klass_obj, :require, Builtin.method(:kernel_require))
|
722
|
-
scratch.set_custom_method(klass_obj, :require_relative, Builtin.method(:kernel_require_relative))
|
723
|
-
scratch.set_custom_method(klass_obj, :Array, Builtin.method(:kernel_Array))
|
724
|
-
scratch.set_custom_method(klass_obj, :autoload, Builtin.method(:kernel_autoload))
|
826
|
+
scratch.set_custom_method(klass_obj, :require, Builtin.method(:kernel_require), false)
|
827
|
+
scratch.set_custom_method(klass_obj, :require_relative, Builtin.method(:kernel_require_relative), false)
|
828
|
+
scratch.set_custom_method(klass_obj, :Array, Builtin.method(:kernel_Array), false)
|
829
|
+
scratch.set_custom_method(klass_obj, :autoload, Builtin.method(:kernel_autoload), false)
|
725
830
|
scratch.set_custom_method(klass_module, :autoload, Builtin.method(:module_autoload))
|
726
831
|
|
727
832
|
# remove BasicObject#method_missing
|