diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2007-06-24 07:29:21 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2007-06-24 07:29:21 +0000 |
commit | 68e02f2c2cc98e6ab736b3122aafe7a2398642f6 (patch) | |
tree | 2167a1299cd58748a883b72de1ba8de0b4128df6 | |
parent | a5c9bf7d63bff7772d7a3b392e9d5ebe6a0bf479 (diff) |
* vm.c (callee_setup_arg): added. support correct post arg.
* vm_macro.def (macro_eval_invoke_func): fix to use
callee_setup_arg.
* compile.c (set_arguments): adjust for above changes.
* compile.c (iseq_compile_each): ditto.
* iseq.c (ruby_iseq_disasm): ditto.
* yarvcore.h: add rb_iseq_t#post_arg_start and arg_size.
* bootstraptest/test_method.rb: add post arg tests.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12594 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | bootstraptest/test_method.rb | 508 | ||||
-rw-r--r-- | compile.c | 148 | ||||
-rw-r--r-- | iseq.c | 8 | ||||
-rw-r--r-- | vm.c | 97 | ||||
-rw-r--r-- | vm_macro.def | 120 | ||||
-rw-r--r-- | yarvcore.h | 3 |
7 files changed, 691 insertions, 210 deletions
@@ -1,3 +1,20 @@ +Sun Jun 24 16:05:45 2007 Koichi Sasada <[email protected]> + + * vm.c (callee_setup_arg): added. support correct post arg. + + * vm_macro.def (macro_eval_invoke_func): fix to use + callee_setup_arg. + + * compile.c (set_arguments): adjust for above changes. + + * compile.c (iseq_compile_each): ditto. + + * iseq.c (ruby_iseq_disasm): ditto. + + * yarvcore.h: add rb_iseq_t#post_arg_start and arg_size. + + * bootstraptest/test_method.rb: add post arg tests. + Sun Jun 24 16:10:43 2007 Nobuyoshi Nakada <[email protected]> * proc.c (proc_to_s): suppress warning, and reduced duplicated code. diff --git a/bootstraptest/test_method.rb b/bootstraptest/test_method.rb index e4f4a82ac3..342803e21b 100644 --- a/bootstraptest/test_method.rb +++ b/bootstraptest/test_method.rb @@ -1,11 +1,25 @@ # regular argument assert_equal '1', 'def m() 1 end; m()' assert_equal '1', 'def m(a) a end; m(1)' -assert_equal '1', 'def m(a,b) a end; m(1,7)' -assert_equal '1', 'def m(a,b) b end; m(7,1)' -assert_equal '1', 'def m(a,b,c) a end; m(1,7,7)' -assert_equal '1', 'def m(a,b,c) b end; m(7,1,7)' -assert_equal '1', 'def m(a,b,c) c end; m(7,7,1)' +assert_equal '[1, 2]', 'def m(a,b) [a, b] end; m(1,2)' +assert_equal '[1, 2, 3]', 'def m(a,b,c) [a, b, c] end; m(1,2,3)' +assert_equal 'wrong number of arguments (1 for 0)', %q{ + def m; end + begin + m(1) + rescue => e + e.message + end +} + +assert_equal 'wrong number of arguments (0 for 1)', %q{ + def m a; end + begin + m + rescue => e + e.message + end +} # default argument assert_equal '1', 'def m(x=1) x end; m()' @@ -303,3 +317,487 @@ assert_equal '1', %q( class C; def m() 7 end; private :m end begin C.new.send(:m); rescue NoMethodError; 1 end ) assert_equal '1', %q( class C; def m() 1 end; private :m end C.new.funcall(:m) ) + + +# post test +assert_equal %q{[1, 2, :o1, :o2, [], 3, 4, NilClass, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4)} + +assert_equal %q{[1, 2, 3, :o2, [], 4, 5, NilClass, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5)} + +assert_equal %q{[1, 2, 3, 4, [], 5, 6, NilClass, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6)} + +assert_equal %q{[1, 2, 3, 4, [5], 6, 7, NilClass, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7)} + +assert_equal %q{[1, 2, 3, 4, [5, 6], 7, 8, NilClass, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7, 8)} + +assert_equal %q{[1, 2, 3, 4, [5, 6, 7], 8, 9, NilClass, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7, 8, 9)} + +assert_equal %q{[1, 2, 3, 4, [5, 6, 7, 8], 9, 10, NilClass, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)} + +assert_equal %q{[1, 2, 3, 4, [5, 6, 7, 8, 9], 10, 11, NilClass, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)} + +assert_equal %q{[1, 2, :o1, :o2, [], 3, 4, Proc, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4){}} + +assert_equal %q{[1, 2, 3, :o2, [], 4, 5, Proc, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5){}} + +assert_equal %q{[1, 2, 3, 4, [], 5, 6, Proc, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6){}} + +assert_equal %q{[1, 2, 3, 4, [5], 6, 7, Proc, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7){}} + +assert_equal %q{[1, 2, 3, 4, [5, 6], 7, 8, Proc, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7, 8){}} + +assert_equal %q{[1, 2, 3, 4, [5, 6, 7], 8, 9, Proc, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7, 8, 9){}} + +assert_equal %q{[1, 2, 3, 4, [5, 6, 7, 8], 9, 10, Proc, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7, 8, 9, 10){}} + +assert_equal %q{[1, 2, 3, 4, [5, 6, 7, 8, 9], 10, 11, Proc, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2, &b) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, b.class, x, y] +end +; m(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11){}} + +assert_equal %q{[1, 2, :o1, :o2, [], 3, 4, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, x, y] +end +; m(1, 2, 3, 4)} + +assert_equal %q{[1, 2, 3, :o2, [], 4, 5, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, x, y] +end +; m(1, 2, 3, 4, 5)} + +assert_equal %q{[1, 2, 3, 4, [], 5, 6, nil, nil]}, %q{ +def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2) + x, y = :x, :y if $foo + [m1, m2, o1, o2, r, p1, p2, x, y] +end +; m(1, 2, 3, 4, 5, 6)} + + +# +# super +# +=begin +# below programs are generated by this program: + +BASE = <<EOS__ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; <TEST>; super; end; end +EOS__ + +tests = { +%q{ + def m +} => %q{ + C1.new.m +}, +# +%q{ + def m a +} => %q{ + C1.new.m 1 +}, +%q{ + def m a + a = :a +} => %q{ + C1.new.m 1 +}, +# +%q{ + def m a, o=:o +} => %q{ + C1.new.m 1 + C1.new.m 1, 2 +}, +%q{ + def m a, o=:o + a = :a +} => %q{ + C1.new.m 1 + C1.new.m 1, 2 +}, +%q{ + def m a, o=:o + o = :x +} => %q{ + C1.new.m 1 + C1.new.m 1, 2 +}, +# +%q{ + def m a, *r +} => %q{ + C1.new.m 1 + C1.new.m 1, 2 + C1.new.m 1, 2, 3 +}, +%q{ + def m a, *r + r = [:x, :y] +} => %q{ + C1.new.m 1 + C1.new.m 1, 2 + C1.new.m 1, 2, 3 +}, +# +%q{ + def m a, o=:o, *r +} => %q{ + C1.new.m 1 + C1.new.m 1, 2 + C1.new.m 1, 2, 3 + C1.new.m 1, 2, 3, 4 +}, +# +%q{ + def m a, o=:o, *r, &b +} => %q{ + C1.new.m 1 + C1.new.m 1, 2 + C1.new.m 1, 2, 3 + C1.new.m 1, 2, 3, 4 + C1.new.m(1){} + C1.new.m(1, 2){} + C1.new.m(1, 2, 3){} + C1.new.m(1, 2, 3, 4){} +}, +# +"def m(m1, m2, o1=:o1, o2=:o2, p1, p2)" => +%q{ +C1.new.m(1,2,3,4) +C1.new.m(1,2,3,4,5) +C1.new.m(1,2,3,4,5,6) +}, +# +"def m(m1, m2, *r, p1, p2)" => +%q{ +C1.new.m(1,2,3,4) +C1.new.m(1,2,3,4,5) +C1.new.m(1,2,3,4,5,6) +C1.new.m(1,2,3,4,5,6,7) +C1.new.m(1,2,3,4,5,6,7,8) +}, +# +"def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2)" => +%q{ +C1.new.m(1,2,3,4) +C1.new.m(1,2,3,4,5) +C1.new.m(1,2,3,4,5,6) +C1.new.m(1,2,3,4,5,6,7) +C1.new.m(1,2,3,4,5,6,7,8) +C1.new.m(1,2,3,4,5,6,7,8,9) +}, + +### +} + + +tests.each{|setup, methods| setup = setup.dup; setup.strip! + setup = BASE.gsub(/<TEST>/){setup} + methods.split(/\n/).each{|m| m = m.dup; m.strip! + next if m.empty? + expr = "#{setup}; #{m}" + result = eval(expr) + puts "assert_equal %q{#{result.inspect}}, %q{\n#{expr}}" + puts + } +} + +=end + +assert_equal %q{[:C0_m, [1, 2, :o1, :o2, 3, 4]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, p1, p2); super; end; end +; C1.new.m(1,2,3,4)} + +assert_equal %q{[:C0_m, [1, 2, 3, :o2, 4, 5]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5, 6]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5,6)} + +assert_equal %q{[:C0_m, [1, :o]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [1, 2]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r; super; end; end +; C1.new.m 1, 2} + +assert_equal %q{[:C0_m, [1, 2, 3]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r; super; end; end +; C1.new.m 1, 2, 3} + +assert_equal %q{[:C0_m, [1, 2, 3, 4]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r; super; end; end +; C1.new.m 1, 2, 3, 4} + +assert_equal %q{[:C0_m, [:a]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a + a = :a; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [1, 2, 3, 4]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5, 6]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5,6)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5, 6, 7]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5,6,7)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5, 6, 7, 8]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5,6,7,8)} + +assert_equal %q{[:C0_m, [1, :o]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r, &b; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [1, 2]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r, &b; super; end; end +; C1.new.m 1, 2} + +assert_equal %q{[:C0_m, [1, 2, 3]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r, &b; super; end; end +; C1.new.m 1, 2, 3} + +assert_equal %q{[:C0_m, [1, 2, 3, 4]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r, &b; super; end; end +; C1.new.m 1, 2, 3, 4} + +assert_equal %q{[:C0_m, [1, :o]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r, &b; super; end; end +; C1.new.m(1){}} + +assert_equal %q{[:C0_m, [1, 2]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r, &b; super; end; end +; C1.new.m(1, 2){}} + +assert_equal %q{[:C0_m, [1, 2, 3]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r, &b; super; end; end +; C1.new.m(1, 2, 3){}} + +assert_equal %q{[:C0_m, [1, 2, 3, 4]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o, *r, &b; super; end; end +; C1.new.m(1, 2, 3, 4){}} + +assert_equal %q{[:C0_m, [1, :x]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o + o = :x; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [1, :x]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o + o = :x; super; end; end +; C1.new.m 1, 2} + +assert_equal %q{[:C0_m, [:a, :o]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o + a = :a; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [:a, 2]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o + a = :a; super; end; end +; C1.new.m 1, 2} + +assert_equal %q{[:C0_m, [1]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [1, :x, :y]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, *r + r = [:x, :y]; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [1, :x, :y]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, *r + r = [:x, :y]; super; end; end +; C1.new.m 1, 2} + +assert_equal %q{[:C0_m, [1, :x, :y]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, *r + r = [:x, :y]; super; end; end +; C1.new.m 1, 2, 3} + +assert_equal %q{[:C0_m, [1, 2, :o1, :o2, 3, 4]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4)} + +assert_equal %q{[:C0_m, [1, 2, 3, :o2, 4, 5]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5, 6]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5,6)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5, 6, 7]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5,6,7)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5, 6, 7, 8]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5,6,7,8)} + +assert_equal %q{[:C0_m, [1, 2, 3, 4, 5, 6, 7, 8, 9]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m(m1, m2, o1=:o1, o2=:o2, *r, p1, p2); super; end; end +; C1.new.m(1,2,3,4,5,6,7,8,9)} + +assert_equal %q{[:C0_m, [1]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, *r; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [1, 2]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, *r; super; end; end +; C1.new.m 1, 2} + +assert_equal %q{[:C0_m, [1, 2, 3]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, *r; super; end; end +; C1.new.m 1, 2, 3} + +assert_equal %q{[:C0_m, []]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m; super; end; end +; C1.new.m} + +assert_equal %q{[:C0_m, [1, :o]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o; super; end; end +; C1.new.m 1} + +assert_equal %q{[:C0_m, [1, 2]]}, %q{ +class C0; def m *args; [:C0_m, args]; end; end +class C1 < C0; def m a, o=:o; super; end; end +; C1.new.m 1, 2} + + + @@ -783,8 +783,6 @@ set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) NODE *node_opt = node_args->nd_opt; ID rest_id = 0; ID block_id = 0; - ID post_start_id = 0; - int post_len = 0; NODE *node_init = 0; int d = iseq->local_size - iseq->local_table_size; @@ -813,8 +811,9 @@ set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) node_aux = node_aux->nd_next; if (node_aux) { - post_start_id = node_aux->nd_pid; - post_len = node_aux->nd_plen; + ID post_start_id = node_aux->nd_pid; + iseq->arg_post_start = get_dyna_var_idx_at_raw(iseq, post_start_id); + iseq->arg_post_len = node_aux->nd_plen; node_init = node_aux->nd_next; } } @@ -861,99 +860,45 @@ set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *optargs, NODE *node_args) } if (rest_id) { - iseq->arg_rest = get_dyna_var_idx_at_raw(iseq, rest_id) + d; + iseq->arg_rest = get_dyna_var_idx_at_raw(iseq, rest_id); if (iseq->arg_rest == -1) { rb_bug("arg_rest: -1"); } - if (post_len) { - /* - * if rest.length < post_len - * raise ArgumentError - * end - * post1 = rest.shift - * post2 = rest.shift - * ... - * - * #=> yarv insns - * push rest - * call :length - * put 1 - * call :< - * branchunless :success - * put ArgumentsError - * put "wrong number of arugments (%d of %d)" - * call :new, 1 - * call :raise - * success: - * push rest - * call :shift - * set post1 - * push rest - * call :shift - * set post2 - * ... - */ - LABEL *lsuccess = NEW_LABEL(nd_line(node_args)); - int i; - -#define GET_LOCAL(idx) do { \ - if (iseq->type == ISEQ_TYPE_METHOD) { \ - ADD_INSN1(optargs, nd_line(node_args), getlocal, INT2FIX(iseq->local_size - (idx) + 1)); \ - } \ - else { \ - ADD_INSN2(optargs, nd_line(node_args), getdynamic, INT2FIX(iseq->local_size - (idx)), INT2FIX(0)); \ - } \ -} while (0) - -#define SET_LOCAL(idx) do { \ - if (iseq->type == ISEQ_TYPE_METHOD) { \ - ADD_INSN1(optargs, nd_line(node_args), setlocal, INT2FIX(iseq->local_size - (idx) + 1)); \ - } \ - else { \ - ADD_INSN2(optargs, nd_line(node_args), setdynamic, INT2FIX(iseq->local_size - (idx)), INT2FIX(0)); \ - } \ -} while (0) - - GET_LOCAL(iseq->arg_rest); - ADD_SEND (optargs, nd_line(node_args), ID2SYM(idLength), INT2FIX(0)); - ADD_INSN1(optargs, nd_line(node_args), putobject, INT2FIX(1)); - ADD_SEND (optargs, nd_line(node_args), ID2SYM(idLT), INT2FIX(1)); - ADD_INSNL(optargs, nd_line(node_args), branchunless, lsuccess); - ADD_CALL_RECEIVER(optargs, nd_line(node_args)); - - /* error */ - ADD_INSN1(optargs, nd_line(node_args), putobject, rb_eArgError); - ADD_INSN1(optargs, nd_line(node_args), putstring, rb_str_new2("wrong number of arguments")); - ADD_SEND (optargs, nd_line(node_args), ID2SYM(rb_intern("new")), INT2FIX(1)); - ADD_CALL (optargs, nd_line(node_args), ID2SYM(rb_intern("raise")), INT2FIX(1)); - ADD_INSN (optargs, nd_line(node_args), pop); /* dummy */ - - ADD_LABEL(optargs, lsuccess); - - for (i=0; i<post_len; i++) { - GET_LOCAL(iseq->arg_rest); - ADD_SEND (optargs, nd_line(node_args), ID2SYM(rb_intern("pop")), - INT2FIX(0)); - SET_LOCAL(iseq->arg_rest + i + 1); + if (iseq->arg_post_start == 0) { + iseq->arg_post_start = iseq->arg_rest + 1; } - - iseq->arg_post_len = post_len; } -#undef GET_LOCAL -#undef SET_LOCAL - } if (block_id) { - iseq->arg_block = get_dyna_var_idx_at_raw(iseq, block_id) + d; + iseq->arg_block = get_dyna_var_idx_at_raw(iseq, block_id); } - if (iseq->arg_opts != 0 || iseq->arg_rest != -1 || iseq->arg_block != -1) { + if (iseq->arg_opts != 0 || iseq->arg_post_len != 0 || + iseq->arg_rest != -1 || iseq->arg_block != -1) { iseq->arg_simple = 0; + + /* set arg_size: size of arguments */ + if (iseq->arg_block != -1) { + iseq->arg_size = iseq->arg_block + 1; + } + else if (iseq->arg_post_len) { + iseq->arg_size = iseq->arg_post_start + iseq->arg_post_len; + } + else if (iseq->arg_rest != -1) { + iseq->arg_size = iseq->arg_rest + 1; + } + else if (iseq->arg_opts) { + iseq->arg_size = iseq->argc + iseq->arg_opts - 1; + } + else { + iseq->arg_size = iseq->argc; + } } else { iseq->arg_simple = 1; + iseq->arg_size = iseq->argc; } } return COMPILE_OK; @@ -3632,29 +3577,46 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) int j; for (j = 0; j < liseq->arg_opts - 1; j++) { int idx = liseq->local_size - (i + j); - ADD_INSN1(args, nd_line(node), getlocal, - INT2FIX(idx)); + ADD_INSN1(args, nd_line(node), getlocal, INT2FIX(idx)); } i += j; argc = INT2FIX(i); } - if (liseq->arg_rest) { - /* rest arguments */ + if (liseq->arg_rest != -1) { + /* rest argument */ + int idx = liseq->local_size - liseq->arg_rest; + ADD_INSN1(args, nd_line(node), getlocal, INT2FIX(idx)); + argc = INT2FIX(liseq->arg_rest + 1); + flag |= VM_CALL_ARGS_SPLAT_BIT; + } + + if (liseq->arg_post_len) { + /* post arguments */ + int post_len = liseq->arg_post_len; + int post_start = liseq->arg_post_start; - if (liseq->arg_rest == -1) { - /* TODO */ + if (liseq->arg_rest != -1) { + int j; + for (j=0; j<post_len; j++) { + int idx = liseq->local_size - (post_start + j); + ADD_INSN1(args, nd_line(node), getlocal, INT2FIX(idx)); + } + ADD_INSN1(args, nd_line(node), newarray, INT2FIX(j)); + ADD_INSN (args, nd_line(node), concatarray); + /* argc is setteled at above */ } else { - int idx = liseq->local_size - liseq->arg_rest + 1; - ADD_INSN1(args, nd_line(node), getlocal, - INT2FIX(idx)); - argc = INT2FIX(liseq->arg_rest); - flag |= VM_CALL_ARGS_SPLAT_BIT; + int j; + for (j=0; j<post_len; j++) { + int idx = liseq->local_size - (post_start + j); + ADD_INSN1(args, nd_line(node), getlocal, INT2FIX(idx)); } + argc = INT2FIX(post_len + post_start); } } } + } /* dummy reciever */ ADD_INSN1(ret, nd_line(node), putobject, @@ -782,11 +782,13 @@ ruby_iseq_disasm(VALUE self) } } - snprintf(argi, sizeof(argi), "%s%s%s%s", /* arg, opts, rest, block */ + snprintf(argi, sizeof(argi), "%s%s%s%s%s", /* arg, opts, rest, post block */ iseqdat->argc > i ? "Arg" : "", opti, - iseqdat->arg_rest - d == i ? "Rest" : "", - iseqdat->arg_block - d == i ? "Block" : ""); + iseqdat->arg_rest == i ? "Rest" : "", + (iseqdat->arg_post_start <= i && + i < iseqdat->arg_post_start + iseqdat->arg_post_len) ? "Post" : "", + iseqdat->arg_block == i ? "Block" : ""); snprintf(info, sizeof(info), "%s%s%s%s", name ? name : "?", *argi ? "<" : "", argi, *argi ? ">" : ""); @@ -184,6 +184,103 @@ th_set_eval_stack(rb_thread_t *th, VALUE iseqval) return 0; } +/* return opt_pc */ +static inline int +callee_setup_arg(rb_thread_t *th, rb_iseq_t *iseq, + int argc, VALUE *argv, rb_block_t **block) +{ + const int m = iseq->argc; + const int orig_argc = argc; + + if (iseq->arg_simple) { + /* simple check */ + if (argc != m) { + rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", + argc, m); + } + return 0; + } + else { + VALUE * const dst = argv; + int opt_pc = 0; + + /* mandatory */ + if (argc < (m + iseq->arg_post_len)) { /* check with post arg */ + rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", + argc, m + iseq->arg_post_len); + } + + argv += m; + argc -= m; + + /* post arguments */ + if (iseq->arg_post_len) { + int i; + + if (!(orig_argc < iseq->arg_post_start)) { + VALUE *new_argv = ALLOCA_N(VALUE, argc); + MEMCPY(new_argv, argv, VALUE, argc); + argv = new_argv; + } + + for (i=0; i<iseq->arg_post_len; i++) { + dst[iseq->arg_post_start + iseq->arg_post_len - (i + 1)] = argv[argc - 1]; + argc = argc - 1; + } + } + + /* opt arguments */ + if (iseq->arg_opts) { + const int opts = iseq->arg_opts - 1 /* no opt */; + + if (iseq->arg_rest == -1 && argc > opts) { + rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", orig_argc, m + opts); + } + + if (argc > opts) { + argc -= opts; + argv += opts; + opt_pc = iseq->arg_opt_tbl[opts]; /* no opt */ + } + else { + opt_pc = iseq->arg_opt_tbl[argc]; + argc = 0; + } + } + + /* rest arguments */ + if (iseq->arg_rest != -1) { + dst[iseq->arg_rest] = rb_ary_new4(argc, argv); + } + + /* block arguments */ + if (iseq->arg_block != -1) { + VALUE blockval = Qnil; + rb_block_t * const blockptr = *block; + + if (blockptr) { + /* make Proc object */ + if (blockptr->proc == 0) { + rb_proc_t *proc; + + th->mark_stack_len = orig_argc; /* for GC */ + blockval = th_make_proc(th, th->cfp, blockptr); + th->mark_stack_len = 0; + + GetProcPtr(blockval, proc); + *block = &proc->block; + } + else { + blockval = blockptr->proc; + } + } + + dst[iseq->arg_block] = blockval; /* Proc or nil */ + } + + return opt_pc; + } +} /* Env */ diff --git a/vm_macro.def b/vm_macro.def index adeaa52ac6..99351efdc5 100644 --- a/vm_macro.def +++ b/vm_macro.def @@ -2,7 +2,6 @@ /* do not use C++ style comment */ /* */ - MACRO macro_eval_setup_send_arguments(num, blockptr, flag, blockiseq) { if (flag & VM_CALL_ARGS_BLOCKARG_BIT) { @@ -83,115 +82,15 @@ MACRO macro_eval_invoke_cfunc(num, id, recv, klass, mn, blockptr) MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num) { rb_iseq_t *niseq; - VALUE *sp = GET_SP(); - VALUE *rsp = sp - num - 1; - int opt_pc = 0, clear_local_size, i; + int opt_pc, i; + VALUE *rsp = GET_SP() - num; + VALUE *sp; /* TODO: eliminate it */ GetISeqPtr(niseqval, niseq); - clear_local_size = niseq->local_size - num; - - /* simple (only mandatory) arguments */ - if (niseq->arg_simple) { - if (niseq->argc != num) { - rb_raise(rb_eArgError, "%d - wrong number of arguments (%lu for %d)", - 0, (unsigned long)num, niseq->argc); - } - } - else { - /* optional arguments */ - if (niseq->arg_opts) { - int iseq_argc = niseq->argc; - int opts = niseq->arg_opts - 1; - - if (num < iseq_argc || - (niseq->arg_rest == -1 && num > iseq_argc + opts)) { - if (0) { - printf("num: %lu, iseq_argc: %d, opts: %d\n", - (unsigned long)num, iseq_argc, opts); - } - rb_raise(rb_eArgError, - "%d - wrong number of arguments (%lu for %d)", - 1, (unsigned long)num, iseq_argc); - } - - if (0) printf("num: %lu, opts: %d, iseq_argc: %d\n", - (unsigned long)num, opts, iseq_argc); - - if (num - iseq_argc < opts) { - opt_pc = niseq->arg_opt_tbl[num - iseq_argc]; - sp += opts - (num - iseq_argc); - num += opts - (num - iseq_argc); - clear_local_size = niseq->local_size - (iseq_argc + opts); - } - else { - opt_pc = niseq->arg_opt_tbl[opts]; - } - } - - /* rest argument */ - if (niseq->arg_rest != -1) { - int rest = niseq->arg_rest - 1 /* spec val */; - int pack_size = num - rest; - - if (0) { - printf("num: %lu, rest: %d, ps: %d\n", - (unsigned long)num, rest, pack_size); - } - - if (pack_size < 0) { - rb_raise(rb_eArgError, - "%d - wrong number of arguments (%lu for %d)", - 2, (unsigned long)num, rest - niseq->arg_opts); - } - - /* - * def m(x, y, z, *a) (rest: 3) => - * x, y, z, a, b, c <SP> (num: 6, pack_size = 3) - * => x, y, z, [a,b,c] <SP> (num: 4) - */ - rsp[rest + 1] = rb_ary_new4(pack_size, &rsp[rest + 1]); - sp = &rsp[rest + 1 + 1]; - num = rest + 1; - clear_local_size = niseq->local_size - (rest + 1); - } - - /* block argument */ - if (niseq->arg_block != -1) { - VALUE arg_block_val = Qnil; - - if (!((num == niseq->arg_rest) || - (niseq->arg_opts && num == niseq->argc + niseq->arg_opts - 1) - || num == niseq->argc)) { - - if (0) printf("num: %d, rest: %d, opts: %d, argc: %d\n", - num, niseq->arg_rest, niseq->arg_opts, niseq->argc); - - rb_raise(rb_eArgError, - "%d - wrong number of arguments (%lu for %d)", - 3, (unsigned long)num, niseq->argc); - } - - if (blockptr) { - /* make Proc object */ - if (blockptr->proc == 0) { - rb_proc_t *proc; - reg_cfp->sp = sp; - arg_block_val = th_make_proc(th, GET_CFP(), blockptr); - GetProcPtr(arg_block_val, proc); - blockptr = &proc->block; - } - else { - arg_block_val = blockptr->proc; - } - } - - rsp[1 + niseq->arg_block - 1] = arg_block_val; - sp++; - clear_local_size--; - } - } + opt_pc = callee_setup_arg(th, niseq, num, rsp, &blockptr); + sp = rsp + niseq->arg_size; /* stack overflow check */ if (CHECK_STACK_OVERFLOW(th, GET_CFP(), niseq->stack_max + 0x100)) { @@ -210,7 +109,7 @@ MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num) sp -= rsp - p_rsp; - for (i = 0; i < clear_local_size; i++) { + for (i = 0; i < niseq->local_size - niseq->arg_size; i++) { *sp++ = Qnil; } @@ -219,7 +118,10 @@ MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num) niseq->iseq_encoded + opt_pc, sp, 0, 0); } else { - for (i = 0; i < clear_local_size; i++) { + if (0) printf("local_size: %d, arg_size: %d\n", + niseq->local_size, niseq->arg_size); + + for (i = 0; i < niseq->local_size - niseq->arg_size; i++) { *sp++ = Qnil; } @@ -227,7 +129,7 @@ MACRO macro_eval_invoke_func(niseqval, recv, klass, blockptr, num) FRAME_MAGIC_METHOD, recv, (VALUE) blockptr, niseq->iseq_encoded + opt_pc, sp, 0, 0); - reg_cfp->sp = rsp; + reg_cfp->sp = rsp - 1 /* recv */; } RESTORE_REGS(); diff --git a/yarvcore.h b/yarvcore.h index ae439a5a60..c33163a570 100644 --- a/yarvcore.h +++ b/yarvcore.h @@ -277,6 +277,9 @@ struct rb_iseq_struct { int arg_block; int arg_opts; int arg_post_len; + int arg_post_start; + int arg_size; + VALUE *arg_opt_tbl; /* for stack overflow check */ |