mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* Merge YARV
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11439 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
3e7566d8fb
commit
a3e1b1ce7e
233 changed files with 46004 additions and 13653 deletions
10
yarvtest/runner.rb
Normal file
10
yarvtest/runner.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
require 'test/unit'
|
||||
|
||||
if $0 == __FILE__
|
||||
# exit Test::Unit::AutoRunner.run(false, File.dirname($0))
|
||||
Dir.glob(File.dirname($0) + '/test_*'){|file|
|
||||
p file
|
||||
require file
|
||||
}
|
||||
end
|
||||
|
585
yarvtest/test_bin.rb
Normal file
585
yarvtest/test_bin.rb
Normal file
|
@ -0,0 +1,585 @@
|
|||
require 'yarvtest/yarvtest'
|
||||
|
||||
# test of basic instruction
|
||||
class TestBIN < YarvTestBase
|
||||
|
||||
def test_literal
|
||||
ae %q(true)
|
||||
ae %q(false)
|
||||
ae %q(nil)
|
||||
ae %q(1234)
|
||||
ae %q(:sym)
|
||||
ae %q(123456789012345678901234567890)
|
||||
ae %q(1.234)
|
||||
ae %q(0x12)
|
||||
ae %q(0b0101001)
|
||||
ae %q(1_2_3) # 123
|
||||
end
|
||||
|
||||
def test_self
|
||||
ae %q(self)
|
||||
end
|
||||
|
||||
def test_string
|
||||
ae %q('str')
|
||||
end
|
||||
|
||||
def test_dstring
|
||||
ae %q(
|
||||
"1+1 = #{1+1}"
|
||||
)
|
||||
ae %q{
|
||||
i = 10
|
||||
"#{i} ** #{i} = #{i ** i}"
|
||||
}
|
||||
ae %q{
|
||||
s = "str"
|
||||
s.__id__ == "#{s}".__id__
|
||||
}
|
||||
end
|
||||
|
||||
def test_dsym
|
||||
ae %q{
|
||||
:"a#{1+2}c"
|
||||
}
|
||||
end
|
||||
|
||||
def test_xstr
|
||||
ae %q(`echo hoge`)
|
||||
ae %q(hoge = 'huga'; `echo #{hoge}`)
|
||||
end
|
||||
|
||||
def test_regexp
|
||||
ae %q{
|
||||
/test/ =~ 'test'
|
||||
}
|
||||
ae %q{
|
||||
/test/ =~ 'tes'
|
||||
}
|
||||
ae %q{
|
||||
r = /test/; l = 'test'
|
||||
r =~ l
|
||||
}
|
||||
ae %q{
|
||||
r = /testx/; l = 'test'
|
||||
r =~ l
|
||||
}
|
||||
ae %q{
|
||||
i = 10
|
||||
/test#{i}/ =~ 'test10'
|
||||
}
|
||||
ae %q{
|
||||
i = 10
|
||||
/test#{i}/ =~ 'test20'
|
||||
}
|
||||
ae %q{
|
||||
:sym =~ /sym/
|
||||
}
|
||||
ae %q{
|
||||
sym = :sym
|
||||
sym =~ /sym/
|
||||
}
|
||||
ae %q{
|
||||
reg = /sym/
|
||||
:sym =~ reg
|
||||
}
|
||||
end
|
||||
|
||||
def test_array
|
||||
ae %q([])
|
||||
ae %q([1,2,3])
|
||||
ae %q([1+1,2+2,3+3])
|
||||
ae %q([0][0]+=3)
|
||||
ae %q([0][0]-=3)
|
||||
end
|
||||
|
||||
def test_array_access
|
||||
ae %q(ary = [1,2,3]; ary[1])
|
||||
ae %q(ary = [1,2,3]; ary[1] = 10)
|
||||
ae %q(ary = Array.new(10, 100); ary[3])
|
||||
end
|
||||
|
||||
def test_hash
|
||||
ae %q({})
|
||||
ae %q({1 => 2})
|
||||
ae %q({"str" => "val", "str2" => "valval"})
|
||||
ae %q({1 => 2, 1=>3})
|
||||
end
|
||||
|
||||
def test_range
|
||||
ae %q((1..2))
|
||||
ae %q((1...2))
|
||||
ae %q(((1+1)..(2+2)))
|
||||
ae %q(((1+1)...(2+2)))
|
||||
end
|
||||
|
||||
def test_not
|
||||
ae %q(!true)
|
||||
ae %q(!nil)
|
||||
ae %q(!false)
|
||||
ae %q(!(1+1))
|
||||
ae %q(!!nil)
|
||||
ae %q(!!1)
|
||||
end
|
||||
|
||||
# var
|
||||
def test_local
|
||||
ae %q(a = 1)
|
||||
ae %q(a = 1; b = 2; a)
|
||||
ae %q(a = b = 3)
|
||||
ae %q(a = b = 3; a)
|
||||
ae %q(a = b = c = 4)
|
||||
ae %q(a = b = c = 4; c)
|
||||
end
|
||||
|
||||
def test_constant
|
||||
ae %q(C = 1; C)
|
||||
ae %q(C = 1; $a = []; 2.times{$a << ::C}; $a)
|
||||
ae %q(
|
||||
class A
|
||||
class B
|
||||
class C
|
||||
Const = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
(1..2).map{
|
||||
A::B::C::Const
|
||||
}
|
||||
) do
|
||||
remove_const :A
|
||||
end
|
||||
|
||||
ae %q(
|
||||
class A
|
||||
class B
|
||||
Const = 1
|
||||
class C
|
||||
(1..2).map{
|
||||
Const
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
) do
|
||||
remove_const :A
|
||||
end
|
||||
|
||||
ae %q(
|
||||
class A
|
||||
Const = 1
|
||||
class B
|
||||
class C
|
||||
(1..2).map{
|
||||
Const
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
) do
|
||||
remove_const :A
|
||||
end
|
||||
|
||||
ae %q(
|
||||
Const = 1
|
||||
class A
|
||||
class B
|
||||
class C
|
||||
(1..2).map{
|
||||
Const
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
) do
|
||||
remove_const :A
|
||||
remove_const :Const
|
||||
end
|
||||
|
||||
ae %q{
|
||||
C = 1
|
||||
begin
|
||||
C::D
|
||||
rescue TypeError
|
||||
:ok
|
||||
else
|
||||
:ng
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_constant2
|
||||
ae %q{
|
||||
class A
|
||||
class B
|
||||
C = 10
|
||||
end
|
||||
end
|
||||
i = 0
|
||||
while i<3
|
||||
i+=1
|
||||
r = A::B::C
|
||||
end
|
||||
r
|
||||
} do
|
||||
remove_const :A
|
||||
end
|
||||
|
||||
ae %q{
|
||||
class A
|
||||
class B
|
||||
C = 10
|
||||
end
|
||||
end
|
||||
i = 0
|
||||
while i<3
|
||||
i+=1
|
||||
r = A::B::C
|
||||
class A::B
|
||||
remove_const :C
|
||||
end
|
||||
A::B::C = i**i
|
||||
end
|
||||
r
|
||||
} do
|
||||
remove_const :A
|
||||
end
|
||||
|
||||
ae %q{
|
||||
class C
|
||||
Const = 1
|
||||
(1..3).map{
|
||||
self::Const
|
||||
}
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
class C
|
||||
Const = 1
|
||||
(1..3).map{
|
||||
eval('self')::Const
|
||||
}
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
class C
|
||||
Const = 0
|
||||
def self.foo()
|
||||
self::Const
|
||||
end
|
||||
end
|
||||
|
||||
class D < C
|
||||
Const = 1
|
||||
end
|
||||
|
||||
class E < C
|
||||
Const = 2
|
||||
end
|
||||
|
||||
[C.foo, D.foo, E.foo]
|
||||
}
|
||||
end
|
||||
|
||||
def test_gvar
|
||||
ae %q(
|
||||
$g1 = 1
|
||||
)
|
||||
|
||||
ae %q(
|
||||
$g2 = 2
|
||||
$g2
|
||||
)
|
||||
end
|
||||
|
||||
def test_cvar
|
||||
ae %q{
|
||||
class C
|
||||
@@c = 1
|
||||
def m
|
||||
@@c += 1
|
||||
end
|
||||
end
|
||||
|
||||
C.new.m
|
||||
} do
|
||||
remove_const :C
|
||||
end
|
||||
end
|
||||
|
||||
def test_cvar_from_singleton
|
||||
ae %q{
|
||||
class C
|
||||
@@c=1
|
||||
class << self
|
||||
def m
|
||||
@@c += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
C.m
|
||||
} do
|
||||
remove_const :C
|
||||
end
|
||||
end
|
||||
|
||||
def test_cvar_from_singleton2
|
||||
ae %q{
|
||||
class C
|
||||
@@c = 1
|
||||
def self.m
|
||||
@@c += 1
|
||||
end
|
||||
end
|
||||
C.m
|
||||
} do
|
||||
remove_const :C
|
||||
end
|
||||
end
|
||||
|
||||
def test_op_asgin2
|
||||
ae %q{
|
||||
class C
|
||||
attr_accessor :a
|
||||
end
|
||||
r = []
|
||||
o = C.new
|
||||
o.a &&= 1
|
||||
r << o.a
|
||||
o.a ||= 2
|
||||
r << o.a
|
||||
o.a &&= 3
|
||||
r << o.a
|
||||
r
|
||||
} do
|
||||
remove_const :C
|
||||
end
|
||||
ae %q{
|
||||
@@x ||= 1
|
||||
}
|
||||
ae %q{
|
||||
@@x = 0
|
||||
@@x ||= 1
|
||||
}
|
||||
end
|
||||
|
||||
def test_op_assgin_and_or
|
||||
ae %q{
|
||||
r = []
|
||||
a = 1 ; a ||= 2; r << a
|
||||
a = nil; a ||= 2; r << a
|
||||
a = 1 ; a &&= 2; r << a
|
||||
a = nil; a &&= 2; r << a
|
||||
r
|
||||
}
|
||||
ae %q{
|
||||
a = {}
|
||||
a[0] ||= 1
|
||||
}
|
||||
ae %q{
|
||||
a = {}
|
||||
a[0] &&= 1
|
||||
}
|
||||
ae %q{
|
||||
a = {0 => 10}
|
||||
a[0] ||= 1
|
||||
}
|
||||
ae %q{
|
||||
a = {0 => 10}
|
||||
a[0] &&= 1
|
||||
}
|
||||
end
|
||||
|
||||
def test_backref
|
||||
ae %q{
|
||||
/a(b)(c)d/ =~ 'xyzabcdefgabcdefg'
|
||||
[$1, $2, $3, $~.class, $&, $`, $', $+]
|
||||
}
|
||||
|
||||
ae %q{
|
||||
def m
|
||||
/a(b)(c)d/ =~ 'xyzabcdefgabcdefg'
|
||||
[$1, $2, $3, $~.class, $&, $`, $', $+]
|
||||
end
|
||||
m
|
||||
}
|
||||
end
|
||||
|
||||
def test_fact
|
||||
ae %q{
|
||||
def fact(n)
|
||||
if(n > 1)
|
||||
n * fact(n-1)
|
||||
else
|
||||
1
|
||||
end
|
||||
end
|
||||
fact(300)
|
||||
}
|
||||
end
|
||||
|
||||
def test_mul
|
||||
ae %q{
|
||||
2*0
|
||||
}
|
||||
ae %q{
|
||||
0*2
|
||||
}
|
||||
ae %q{
|
||||
2*2
|
||||
}
|
||||
end
|
||||
|
||||
def test_div
|
||||
ae %q{
|
||||
3/2
|
||||
}
|
||||
ae %q{
|
||||
3.0/2.0
|
||||
}
|
||||
ae %q{
|
||||
class C
|
||||
def /(a)
|
||||
a * 100
|
||||
end
|
||||
end
|
||||
C.new/3
|
||||
} do
|
||||
remove_const :C
|
||||
end
|
||||
end
|
||||
|
||||
def test_length
|
||||
ae %q{
|
||||
[].length
|
||||
}
|
||||
ae %q{
|
||||
[1, 2].length
|
||||
}
|
||||
ae %q{
|
||||
{}.length
|
||||
}
|
||||
ae %q{
|
||||
{:a => 1, :b => 2}.length
|
||||
}
|
||||
ae %q{
|
||||
class C
|
||||
def length
|
||||
'hoge'
|
||||
end
|
||||
end
|
||||
C.new.length
|
||||
} do
|
||||
remove_const :C
|
||||
end
|
||||
end
|
||||
|
||||
def test_mod
|
||||
ae %q{
|
||||
3%2
|
||||
}
|
||||
ae %q{
|
||||
3.0%2.0
|
||||
}
|
||||
ae %q{
|
||||
class C
|
||||
def % (a)
|
||||
a * 100
|
||||
end
|
||||
end
|
||||
C.new%3
|
||||
} do
|
||||
remove_const :C
|
||||
end
|
||||
end
|
||||
|
||||
def test_attr_set
|
||||
ae %q{
|
||||
o = Object.new
|
||||
def o.[]=(*args)
|
||||
args
|
||||
end
|
||||
[o[]=:x, o[0]=:x, o[0, 1]=:x, o[0, 1, 2]=:x]
|
||||
}
|
||||
ae %q{
|
||||
o = Object.new
|
||||
def o.foo=(*args)
|
||||
args
|
||||
end
|
||||
o.foo = :x
|
||||
}
|
||||
ae %q{
|
||||
$r = []
|
||||
class C
|
||||
def [](*args)
|
||||
$r << [:ref, args]
|
||||
args.size
|
||||
end
|
||||
|
||||
def []=(*args)
|
||||
$r << [:set, args]
|
||||
args.size
|
||||
end
|
||||
end
|
||||
|
||||
o = C.new
|
||||
ary = [:x, :y]
|
||||
o[1] = 2
|
||||
o[1, 2] = 3
|
||||
o[1, 2, *ary] = 3
|
||||
o[1, 2, *ary, 3] = 4
|
||||
$r
|
||||
}
|
||||
end
|
||||
|
||||
def test_aref_aset
|
||||
ae %q{
|
||||
a = []
|
||||
a << 0
|
||||
a[1] = 1
|
||||
a[2] = 2
|
||||
a[3] = a[1] + a[2]
|
||||
}
|
||||
ae %q{
|
||||
a = {}
|
||||
a[1] = 1
|
||||
a[2] = 2
|
||||
a[3] = a[1] + a[2]
|
||||
a.sort
|
||||
}
|
||||
ae %q{
|
||||
class C
|
||||
attr_reader :a, :b
|
||||
def [](a)
|
||||
@a = a
|
||||
end
|
||||
|
||||
def []=(a, b)
|
||||
@b = [a, b]
|
||||
end
|
||||
end
|
||||
c = C.new
|
||||
c[3]
|
||||
c[4] = 5
|
||||
[c.a, c.b]
|
||||
} do
|
||||
remove_const :C
|
||||
end
|
||||
end
|
||||
|
||||
def test_array_concat
|
||||
ae %q{
|
||||
ary = []
|
||||
[:x, *ary]
|
||||
}
|
||||
#ae %q{
|
||||
# ary = 1
|
||||
# [:x, *ary]
|
||||
#}
|
||||
ae %q{
|
||||
ary = [1, 2]
|
||||
[:x, *ary]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
429
yarvtest/test_block.rb
Normal file
429
yarvtest/test_block.rb
Normal file
|
@ -0,0 +1,429 @@
|
|||
require 'yarvtest/yarvtest'
|
||||
|
||||
class TestBlock < YarvTestBase
|
||||
def test_simple
|
||||
ae %q(
|
||||
def m
|
||||
yield
|
||||
end
|
||||
m{
|
||||
1
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
def test_param
|
||||
ae %q(
|
||||
def m
|
||||
yield 1
|
||||
end
|
||||
m{|ib|
|
||||
ib*2
|
||||
}
|
||||
)
|
||||
|
||||
ae %q(
|
||||
def m
|
||||
yield 12345, 67890
|
||||
end
|
||||
m{|ib,jb|
|
||||
ib*2+jb
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
def test_param2
|
||||
ae %q{
|
||||
def iter
|
||||
yield 10
|
||||
end
|
||||
|
||||
a = nil
|
||||
[iter{|a|
|
||||
a
|
||||
}, a]
|
||||
}
|
||||
ae %q{
|
||||
def iter
|
||||
yield 10
|
||||
end
|
||||
|
||||
iter{|a|
|
||||
iter{|a|
|
||||
a + 1
|
||||
} + a
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
def iter
|
||||
yield 10, 20, 30, 40
|
||||
end
|
||||
|
||||
a = b = c = d = nil
|
||||
iter{|a, b, c, d|
|
||||
[a, b, c, d]
|
||||
} + [a, b, c, d]
|
||||
}
|
||||
ae %q{
|
||||
def iter
|
||||
yield 10, 20, 30, 40
|
||||
end
|
||||
|
||||
a = b = nil
|
||||
iter{|a, b, c, d|
|
||||
[a, b, c, d]
|
||||
} + [a, b]
|
||||
}
|
||||
ae %q{
|
||||
def iter
|
||||
yield 10, 20, 30, 40
|
||||
end
|
||||
|
||||
a = nil
|
||||
iter{|a, $b, @c, d|
|
||||
[a, $b]
|
||||
} + [a, $b, @c]
|
||||
} if false # 1.9 doesn't support expr block parameters
|
||||
end
|
||||
|
||||
def test_param3
|
||||
if false
|
||||
# TODO: Ruby 1.9 doesn't support expr block parameter
|
||||
ae %q{
|
||||
h = {}
|
||||
[1].each{|h[:foo]|}
|
||||
h
|
||||
}
|
||||
ae %q{
|
||||
obj = Object.new
|
||||
def obj.x=(y)
|
||||
$ans = y
|
||||
end
|
||||
[1].each{|obj.x|}
|
||||
$ans
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_blocklocal
|
||||
ae %q{
|
||||
1.times{
|
||||
begin
|
||||
a = 1
|
||||
ensure
|
||||
foo = nil
|
||||
end
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_simplenest
|
||||
ae %q(
|
||||
def m
|
||||
yield 123
|
||||
end
|
||||
m{|ib|
|
||||
m{|jb|
|
||||
ib*jb
|
||||
}
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
def test_simplenest2
|
||||
ae %q(
|
||||
def m a
|
||||
yield a
|
||||
end
|
||||
m(1){|ib|
|
||||
m(2){|jb|
|
||||
ib*jb
|
||||
}
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
def test_nest2
|
||||
ae %q(
|
||||
def m
|
||||
yield
|
||||
end
|
||||
def n
|
||||
yield
|
||||
end
|
||||
|
||||
m{
|
||||
n{
|
||||
100
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
ae %q(
|
||||
def m
|
||||
yield 1
|
||||
end
|
||||
|
||||
m{|ib|
|
||||
m{|jb|
|
||||
i = 20
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
ae %q(
|
||||
def m
|
||||
yield 1
|
||||
end
|
||||
|
||||
m{|ib|
|
||||
m{|jb|
|
||||
ib = 20
|
||||
kb = 2
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
ae %q(
|
||||
def iter1
|
||||
iter2{
|
||||
yield
|
||||
}
|
||||
end
|
||||
|
||||
def iter2
|
||||
yield
|
||||
end
|
||||
|
||||
iter1{
|
||||
jb = 2
|
||||
iter1{
|
||||
jb = 3
|
||||
}
|
||||
jb
|
||||
}
|
||||
)
|
||||
|
||||
ae %q(
|
||||
def iter1
|
||||
iter2{
|
||||
yield
|
||||
}
|
||||
end
|
||||
|
||||
def iter2
|
||||
yield
|
||||
end
|
||||
|
||||
iter1{
|
||||
jb = 2
|
||||
iter1{
|
||||
jb
|
||||
}
|
||||
jb
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
def test_ifunc
|
||||
ae %q{
|
||||
(1..3).to_a
|
||||
}
|
||||
|
||||
ae %q{
|
||||
(1..3).map{|e|
|
||||
e * 4
|
||||
}
|
||||
}
|
||||
|
||||
ae %q{
|
||||
class C
|
||||
include Enumerable
|
||||
def each
|
||||
[1,2,3].each{|e|
|
||||
yield e
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
C.new.to_a
|
||||
}
|
||||
|
||||
ae %q{
|
||||
class C
|
||||
include Enumerable
|
||||
def each
|
||||
[1,2,3].each{|e|
|
||||
yield e
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
C.new.map{|e|
|
||||
e + 3
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_times
|
||||
ae %q{
|
||||
sum = 0
|
||||
3.times{|ib|
|
||||
2.times{|jb|
|
||||
sum += ib + jb
|
||||
}}
|
||||
sum
|
||||
}
|
||||
ae %q{
|
||||
3.times{|bl|
|
||||
break 10
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_for
|
||||
ae %q{
|
||||
sum = 0
|
||||
for x in [1, 2, 3]
|
||||
sum += x
|
||||
end
|
||||
sum
|
||||
}
|
||||
ae %q{
|
||||
sum = 0
|
||||
for x in (1..5)
|
||||
sum += x
|
||||
end
|
||||
sum
|
||||
}
|
||||
ae %q{
|
||||
sum = 0
|
||||
for x in []
|
||||
sum += x
|
||||
end
|
||||
sum
|
||||
}
|
||||
ae %q{
|
||||
ans = []
|
||||
1.times{
|
||||
for n in 1..3
|
||||
a = n
|
||||
ans << a
|
||||
end
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
ans = []
|
||||
for m in 1..3
|
||||
for n in 1..3
|
||||
a = [m, n]
|
||||
ans << a
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_unmatched_params
|
||||
ae %q{
|
||||
def iter
|
||||
yield 1,2,3
|
||||
end
|
||||
|
||||
iter{|i, j|
|
||||
[i, j]
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
def iter
|
||||
yield 1
|
||||
end
|
||||
|
||||
iter{|i, j|
|
||||
[i, j]
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_rest
|
||||
# TODO: known bug
|
||||
#ae %q{
|
||||
# def iter
|
||||
# yield 1, 2
|
||||
# end
|
||||
#
|
||||
# iter{|a, |
|
||||
# [a]
|
||||
# }
|
||||
#}
|
||||
ae %q{
|
||||
def iter
|
||||
yield 1, 2
|
||||
end
|
||||
|
||||
iter{|a, *b|
|
||||
[a, b]
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
def iter
|
||||
yield 1, 2
|
||||
end
|
||||
|
||||
iter{|*a|
|
||||
[a]
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
def iter
|
||||
yield 1, 2
|
||||
end
|
||||
|
||||
iter{|a, b, *c|
|
||||
[a, b, c]
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
def iter
|
||||
yield 1, 2
|
||||
end
|
||||
|
||||
iter{|a, b, c, *d|
|
||||
[a, b, c, d]
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_param_and_locals
|
||||
ae %q{
|
||||
$a = []
|
||||
|
||||
def iter
|
||||
yield 1
|
||||
end
|
||||
|
||||
def m
|
||||
x = iter{|x|
|
||||
$a << x
|
||||
y = 0
|
||||
}
|
||||
end
|
||||
m
|
||||
$a
|
||||
}
|
||||
end
|
||||
|
||||
def test_c_break
|
||||
ae %q{
|
||||
[1,2,3].find{|x| x == 2}
|
||||
}
|
||||
ae %q{
|
||||
class E
|
||||
include Enumerable
|
||||
def each(&block)
|
||||
[1, 2, 3].each(&block)
|
||||
end
|
||||
end
|
||||
E.new.find {|x| x == 2 }
|
||||
}
|
||||
end
|
||||
end
|
753
yarvtest/test_class.rb
Normal file
753
yarvtest/test_class.rb
Normal file
|
@ -0,0 +1,753 @@
|
|||
require 'yarvtest/yarvtest'
|
||||
|
||||
class TestClass < YarvTestBase
|
||||
|
||||
def test_simple
|
||||
ae %q(
|
||||
class C
|
||||
def m(a,b)
|
||||
a+b
|
||||
end
|
||||
end
|
||||
C.new.m(1,2)
|
||||
) do
|
||||
remove_const(:C)
|
||||
end
|
||||
|
||||
ae %q(
|
||||
class A
|
||||
end
|
||||
class A::B
|
||||
def m
|
||||
A::B.name
|
||||
end
|
||||
end
|
||||
A::B.new.m
|
||||
) do
|
||||
remove_const(:A)
|
||||
end
|
||||
|
||||
#ae %q(
|
||||
# class (class C;self; end)::D < C
|
||||
# self.name
|
||||
# end
|
||||
#) do
|
||||
# remove_const(:C)
|
||||
#end
|
||||
|
||||
end
|
||||
|
||||
def test_sub
|
||||
ae %q(
|
||||
class A
|
||||
def m
|
||||
123
|
||||
end
|
||||
end
|
||||
|
||||
class B < A
|
||||
end
|
||||
|
||||
B.new.m
|
||||
) do
|
||||
remove_const(:A)
|
||||
remove_const(:B)
|
||||
end
|
||||
|
||||
ae %q(
|
||||
class A
|
||||
class B
|
||||
class C
|
||||
def m
|
||||
456
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class A::BB < A::B::C
|
||||
end
|
||||
|
||||
A::BB.new.m
|
||||
) do
|
||||
remove_const(:A)
|
||||
end
|
||||
end
|
||||
|
||||
def test_attr
|
||||
ae %q(
|
||||
class C
|
||||
def set
|
||||
@a = 1
|
||||
end
|
||||
def get
|
||||
@a
|
||||
end
|
||||
end
|
||||
c = C.new
|
||||
c.set
|
||||
c.get
|
||||
) do
|
||||
remove_const(:C)
|
||||
end
|
||||
end
|
||||
|
||||
def test_initialize
|
||||
ae %q{
|
||||
class C
|
||||
def initialize
|
||||
@a = :C
|
||||
end
|
||||
def a
|
||||
@a
|
||||
end
|
||||
end
|
||||
|
||||
C.new.a
|
||||
} do
|
||||
remove_const(:C)
|
||||
end
|
||||
end
|
||||
|
||||
def test_to_s
|
||||
ae %q{
|
||||
class C
|
||||
def to_s
|
||||
"hoge"
|
||||
end
|
||||
end
|
||||
|
||||
"ab#{C.new}cd"
|
||||
} do
|
||||
remove_const(:C)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def test_attr_accessor
|
||||
ae %q{
|
||||
class C
|
||||
attr_accessor :a
|
||||
attr_reader :b
|
||||
attr_writer :c
|
||||
def b_write
|
||||
@b = 'huga'
|
||||
end
|
||||
def m a
|
||||
'test_attr_accessor' + @b + @c
|
||||
end
|
||||
end
|
||||
|
||||
c = C.new
|
||||
c.a = true
|
||||
c.c = 'hoge'
|
||||
c.b_write
|
||||
c.m(c.b)
|
||||
} do
|
||||
remove_const(:C)
|
||||
end
|
||||
end
|
||||
|
||||
def test_super
|
||||
ae %q{
|
||||
class C
|
||||
def m1
|
||||
100
|
||||
end
|
||||
|
||||
def m2 a
|
||||
a + 100
|
||||
end
|
||||
end
|
||||
|
||||
class CC < C
|
||||
def m1
|
||||
super() * 100
|
||||
end
|
||||
|
||||
def m2
|
||||
super(200) * 100
|
||||
end
|
||||
end
|
||||
|
||||
a = CC.new
|
||||
a.m1 + a.m2
|
||||
} do
|
||||
remove_const(:C)
|
||||
remove_const(:CC)
|
||||
end
|
||||
end
|
||||
|
||||
def test_super2
|
||||
ae %q{
|
||||
class C
|
||||
def m(a, b)
|
||||
a+b
|
||||
end
|
||||
end
|
||||
|
||||
class D < C
|
||||
def m arg
|
||||
super(*arg) + super(1, arg.shift)
|
||||
end
|
||||
end
|
||||
|
||||
D.new.m([1, 2])
|
||||
}
|
||||
|
||||
ae %q{
|
||||
class C
|
||||
def m
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
class D < C
|
||||
def m
|
||||
super(){
|
||||
:D
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
D.new.m{
|
||||
:top
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
class C0
|
||||
def m a, &b
|
||||
[a, b]
|
||||
end
|
||||
end
|
||||
|
||||
class C1 < C0
|
||||
def m a, &b
|
||||
super a, &b
|
||||
end
|
||||
end
|
||||
|
||||
C1.new.m(10)
|
||||
}
|
||||
end
|
||||
|
||||
def test_zsuper_from_define_method
|
||||
ae %q{
|
||||
class C
|
||||
def a
|
||||
"C#a"
|
||||
end
|
||||
def m
|
||||
"C#m"
|
||||
end
|
||||
end
|
||||
class D < C
|
||||
define_method(:m){
|
||||
super
|
||||
}
|
||||
define_method(:a){
|
||||
r = nil
|
||||
1.times{
|
||||
r = super
|
||||
}
|
||||
r
|
||||
}
|
||||
end
|
||||
D.new.m + D.new.a
|
||||
}
|
||||
ae %q{
|
||||
class X
|
||||
def a
|
||||
"X#a"
|
||||
end
|
||||
def b
|
||||
class << self
|
||||
define_method(:a) {
|
||||
super
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
x = X.new
|
||||
x.b
|
||||
x.a
|
||||
}
|
||||
ae %q{
|
||||
class C
|
||||
def m arg
|
||||
"C#m(#{arg})"
|
||||
end
|
||||
def b
|
||||
class << self
|
||||
define_method(:m){|a|
|
||||
super
|
||||
}
|
||||
end
|
||||
self
|
||||
end
|
||||
end
|
||||
C.new.b.m(:ok)
|
||||
}
|
||||
ae %q{
|
||||
class C
|
||||
def m *args
|
||||
"C#m(#{args.join(', ')})"
|
||||
end
|
||||
def b
|
||||
class << self
|
||||
define_method(:m){|a, b|
|
||||
r = nil
|
||||
1.times{
|
||||
r = super
|
||||
}
|
||||
r
|
||||
}
|
||||
end
|
||||
self
|
||||
end
|
||||
end
|
||||
C.new.b.m(:ok1, :ok2)
|
||||
} if false # ruby 1.9 dumped core
|
||||
ae %q{ # [yarv-dev:859]
|
||||
$ans = []
|
||||
class A
|
||||
def m_a
|
||||
$ans << "m_a"
|
||||
end
|
||||
def def_m_a
|
||||
$ans << "def_m_a"
|
||||
end
|
||||
end
|
||||
class B < A
|
||||
def def_m_a
|
||||
B.class_eval{
|
||||
super
|
||||
define_method(:m_a) do
|
||||
super
|
||||
end
|
||||
}
|
||||
super
|
||||
end
|
||||
end
|
||||
b = B.new
|
||||
b.def_m_a
|
||||
b.m_a
|
||||
$ans
|
||||
}
|
||||
ae %q{
|
||||
class A
|
||||
def hoge
|
||||
:hoge
|
||||
end
|
||||
def foo
|
||||
:foo
|
||||
end
|
||||
end
|
||||
class B < A
|
||||
def memoize(name)
|
||||
B.instance_eval do
|
||||
define_method(name) do
|
||||
[name, super]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
b = B.new
|
||||
b.memoize(:hoge)
|
||||
b.memoize(:foo)
|
||||
[b.foo, b.hoge]
|
||||
}
|
||||
end
|
||||
|
||||
def test_zsuper
|
||||
ae %q{
|
||||
class C
|
||||
def m1
|
||||
100
|
||||
end
|
||||
|
||||
def m2 a
|
||||
a + 100
|
||||
end
|
||||
|
||||
def m3 a
|
||||
a + 200
|
||||
end
|
||||
end
|
||||
|
||||
class CC < C
|
||||
def m1
|
||||
super * 100
|
||||
end
|
||||
|
||||
def m2 a
|
||||
super * 100
|
||||
end
|
||||
|
||||
def m3 a
|
||||
a = 400
|
||||
super * 100
|
||||
end
|
||||
end
|
||||
|
||||
a = CC.new
|
||||
a.m1 + a.m2(200) + a.m3(300)
|
||||
} do
|
||||
remove_const(:C)
|
||||
remove_const(:CC)
|
||||
end
|
||||
end
|
||||
|
||||
def test_zsuper2
|
||||
ae %q{
|
||||
class C1
|
||||
def m
|
||||
10
|
||||
end
|
||||
end
|
||||
|
||||
class C2 < C1
|
||||
def m
|
||||
20 + super
|
||||
end
|
||||
end
|
||||
|
||||
class C3 < C2
|
||||
def m
|
||||
30 + super
|
||||
end
|
||||
end
|
||||
|
||||
C3.new.m
|
||||
} do
|
||||
remove_const(:C1)
|
||||
remove_const(:C2)
|
||||
remove_const(:C3)
|
||||
end
|
||||
|
||||
ae %q{
|
||||
class C
|
||||
def m
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
class D < C
|
||||
def m
|
||||
super{
|
||||
:D
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
D.new.m{
|
||||
:top
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
class C
|
||||
def m(a, b, c, d)
|
||||
a+b+c+d
|
||||
end
|
||||
end
|
||||
|
||||
class D < C
|
||||
def m(a, b=1, c=2, *d)
|
||||
d[0] ||= 0.1
|
||||
[super,
|
||||
begin
|
||||
a *= 2
|
||||
b *= 3
|
||||
c *= 4
|
||||
d[0] *= 5
|
||||
super
|
||||
end
|
||||
]
|
||||
end
|
||||
end
|
||||
ary = []
|
||||
ary << D.new.m(10, 20, 30, 40)
|
||||
if false # On current ruby, these programs don't work
|
||||
ary << D.new.m(10, 20, 30)
|
||||
ary << D.new.m(10, 20)
|
||||
ary << D.new.m(10)
|
||||
end
|
||||
ary
|
||||
}
|
||||
ae %q{
|
||||
class C
|
||||
def m(a, b, c, d)
|
||||
a+b+c+d
|
||||
end
|
||||
end
|
||||
|
||||
class D < C
|
||||
def m(a, b=1, c=2, d=3)
|
||||
[super,
|
||||
begin
|
||||
a *= 2
|
||||
b *= 3
|
||||
c *= 4
|
||||
d *= 5
|
||||
super
|
||||
end
|
||||
]
|
||||
end
|
||||
end
|
||||
ary = []
|
||||
ary << D.new.m(10, 20, 30, 40)
|
||||
ary << D.new.m(10, 20, 30)
|
||||
ary << D.new.m(10, 20)
|
||||
ary << D.new.m(10)
|
||||
ary
|
||||
}
|
||||
ae %q{
|
||||
class C
|
||||
def m(a, b, c, d, &e)
|
||||
a+b+c+d+e.call
|
||||
end
|
||||
def n(a, b, c, d, &e)
|
||||
a+b+c+d+e.call
|
||||
end
|
||||
end
|
||||
|
||||
class D < C
|
||||
def m(a, b=1, c=2, *d, &e)
|
||||
super
|
||||
end
|
||||
def n(a, b=1, c=2, d=3, &e)
|
||||
super
|
||||
end
|
||||
end
|
||||
ary = []
|
||||
ary << D.new.m(1, 2, 3, 4){
|
||||
5
|
||||
}
|
||||
ary << D.new.m(1, 2, 3, 4, &lambda{
|
||||
5
|
||||
})
|
||||
ary << D.new.n(1, 2, 3){
|
||||
5
|
||||
}
|
||||
ary << D.new.n(1, 2){
|
||||
5
|
||||
}
|
||||
ary << D.new.n(1){
|
||||
5
|
||||
}
|
||||
ary
|
||||
}
|
||||
end
|
||||
|
||||
def test_super_with_private
|
||||
ae %q{
|
||||
class C
|
||||
private
|
||||
def m1
|
||||
:OK
|
||||
end
|
||||
protected
|
||||
def m2
|
||||
end
|
||||
end
|
||||
class D < C
|
||||
def m1
|
||||
[super, super()]
|
||||
end
|
||||
def m2
|
||||
[super, super()]
|
||||
end
|
||||
end
|
||||
D.new.m1 + D.new.m2
|
||||
}
|
||||
end
|
||||
|
||||
def test_const_in_other_scope
|
||||
ae %q{
|
||||
class C
|
||||
Const = :ok
|
||||
def m
|
||||
1.times{
|
||||
Const
|
||||
}
|
||||
end
|
||||
end
|
||||
C.new.m
|
||||
} do
|
||||
remove_const(:C)
|
||||
end
|
||||
|
||||
ae %q{
|
||||
class C
|
||||
Const = 1
|
||||
def m
|
||||
begin
|
||||
raise
|
||||
rescue
|
||||
Const
|
||||
end
|
||||
end
|
||||
end
|
||||
C.new.m
|
||||
} do
|
||||
remove_const(:C)
|
||||
end
|
||||
end
|
||||
|
||||
def test_reopen_not_class
|
||||
ae %q{ # [yarv-dev:782]
|
||||
begin
|
||||
B = 1
|
||||
class B
|
||||
p B
|
||||
end
|
||||
rescue TypeError => e
|
||||
e.message
|
||||
end
|
||||
}
|
||||
ae %q{ # [yarv-dev:800]
|
||||
begin
|
||||
B = 1
|
||||
module B
|
||||
p B
|
||||
end
|
||||
rescue TypeError => e
|
||||
e.message
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_set_const_not_class
|
||||
ae %q{
|
||||
begin
|
||||
1::A = 1
|
||||
rescue TypeError => e
|
||||
e.message
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_singletonclass
|
||||
ae %q{
|
||||
obj = ''
|
||||
class << obj
|
||||
def m
|
||||
:OK
|
||||
end
|
||||
end
|
||||
obj.m
|
||||
}
|
||||
ae %q{
|
||||
obj = ''
|
||||
Const = :NG
|
||||
class << obj
|
||||
Const = :OK
|
||||
def m
|
||||
Const
|
||||
end
|
||||
end
|
||||
obj.m
|
||||
}
|
||||
ae %q{
|
||||
obj = ''
|
||||
class C
|
||||
def m
|
||||
:NG
|
||||
end
|
||||
end
|
||||
class << obj
|
||||
class C
|
||||
def m
|
||||
:OK
|
||||
end
|
||||
end
|
||||
def m
|
||||
C.new.m
|
||||
end
|
||||
end
|
||||
obj.m
|
||||
}
|
||||
ae %q{ # [yarv-dev:818]
|
||||
class A
|
||||
end
|
||||
class << A
|
||||
C = "OK"
|
||||
def m
|
||||
class << Object
|
||||
$a = C
|
||||
end
|
||||
end
|
||||
end
|
||||
A.m
|
||||
$a
|
||||
}
|
||||
end
|
||||
|
||||
def test_include
|
||||
ae %q{
|
||||
module M
|
||||
class A
|
||||
def hoge
|
||||
"hoge"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class A
|
||||
include M
|
||||
def m
|
||||
[Module.nesting, A.new.hoge, instance_eval("A.new.hoge")]
|
||||
end
|
||||
end
|
||||
A.new.m
|
||||
}
|
||||
end
|
||||
|
||||
def test_colon3
|
||||
ae %q{
|
||||
class A
|
||||
::B = :OK
|
||||
end
|
||||
B
|
||||
}
|
||||
ae %q{
|
||||
class A
|
||||
class ::C
|
||||
end
|
||||
end
|
||||
C
|
||||
}
|
||||
end
|
||||
|
||||
def test_undef
|
||||
# [yarv-dev:999]
|
||||
ae %q{
|
||||
class Parent
|
||||
def foo
|
||||
end
|
||||
end
|
||||
class Child < Parent
|
||||
def bar
|
||||
end
|
||||
|
||||
undef foo, bar
|
||||
end
|
||||
|
||||
c = Child.new
|
||||
[c.methods.include?('foo'), c.methods.include?('bar')]
|
||||
}
|
||||
end
|
||||
|
||||
def test_dup
|
||||
ae %q{
|
||||
ObjectSpace.each_object{|obj|
|
||||
if Module === obj && (obj.respond_to? :dup)
|
||||
obj.dup
|
||||
end
|
||||
}
|
||||
:ok
|
||||
}
|
||||
end
|
||||
end
|
||||
|
213
yarvtest/test_eval.rb
Normal file
213
yarvtest/test_eval.rb
Normal file
|
@ -0,0 +1,213 @@
|
|||
require 'yarvtest/yarvtest'
|
||||
|
||||
class TestEval < YarvTestBase
|
||||
def test_eval
|
||||
ae %q{
|
||||
eval('1')
|
||||
}
|
||||
ae %q{
|
||||
eval('a=1; a')
|
||||
}
|
||||
ae %q{
|
||||
a = 1
|
||||
eval('a')
|
||||
}
|
||||
end
|
||||
|
||||
def test_eval_with_send
|
||||
ae %q{
|
||||
__send! :eval, %{
|
||||
:ok
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
1.__send! :instance_eval, %{
|
||||
:ok
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_module_eval
|
||||
ae %q{
|
||||
Const = :top
|
||||
class C
|
||||
Const = :C
|
||||
end
|
||||
C.module_eval{
|
||||
Const
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
Const = :top
|
||||
class C
|
||||
Const = :C
|
||||
end
|
||||
C.module_eval %{
|
||||
Const
|
||||
}
|
||||
} if false # TODO: Ruby 1.9 error
|
||||
|
||||
ae %q{
|
||||
Const = :top
|
||||
class C
|
||||
Const = :C
|
||||
end
|
||||
C.class_eval %{
|
||||
def m
|
||||
Const
|
||||
end
|
||||
}
|
||||
C.new.m
|
||||
}
|
||||
ae %q{
|
||||
Const = :top
|
||||
class C
|
||||
Const = :C
|
||||
end
|
||||
C.class_eval{
|
||||
def m
|
||||
Const
|
||||
end
|
||||
}
|
||||
C.new.m
|
||||
}
|
||||
end
|
||||
|
||||
def test_instance_eval
|
||||
ae %q{
|
||||
1.instance_eval{
|
||||
self
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
'foo'.instance_eval{
|
||||
self
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
class Fixnum
|
||||
Const = 1
|
||||
end
|
||||
1.instance_eval %{
|
||||
Const
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_nest_eval
|
||||
ae %q{
|
||||
Const = :top
|
||||
class C
|
||||
Const = :C
|
||||
end
|
||||
$nest = false
|
||||
$ans = []
|
||||
def m
|
||||
$ans << Const
|
||||
C.module_eval %{
|
||||
$ans << Const
|
||||
Boo = false unless defined? Boo
|
||||
unless $nest
|
||||
$nest = true
|
||||
m
|
||||
end
|
||||
}
|
||||
end
|
||||
m
|
||||
$ans
|
||||
}
|
||||
ae %q{
|
||||
$nested = false
|
||||
$ans = []
|
||||
$pr = proc{
|
||||
$ans << self
|
||||
unless $nested
|
||||
$nested = true
|
||||
$pr.call
|
||||
end
|
||||
}
|
||||
class C
|
||||
def initialize &b
|
||||
10.instance_eval(&b)
|
||||
end
|
||||
end
|
||||
C.new(&$pr)
|
||||
$ans
|
||||
}
|
||||
end
|
||||
|
||||
def test_binding
|
||||
ae %q{
|
||||
def m
|
||||
a = :ok
|
||||
$b = binding
|
||||
end
|
||||
m
|
||||
eval('a', $b)
|
||||
}
|
||||
ae %q{
|
||||
def m
|
||||
a = :ok
|
||||
$b = binding
|
||||
end
|
||||
m
|
||||
eval('b = :ok2', $b)
|
||||
eval('[a, b]', $b)
|
||||
}
|
||||
ae %q{
|
||||
$ans = []
|
||||
def m
|
||||
$b = binding
|
||||
end
|
||||
m
|
||||
$ans << eval(%q{
|
||||
$ans << eval(%q{
|
||||
a
|
||||
}, $b)
|
||||
a = 1
|
||||
}, $b)
|
||||
$ans
|
||||
}
|
||||
ae %q{
|
||||
Const = :top
|
||||
class C
|
||||
Const = :C
|
||||
def m
|
||||
binding
|
||||
end
|
||||
end
|
||||
eval('Const', C.new.m)
|
||||
}
|
||||
ae %q{
|
||||
Const = :top
|
||||
a = 1
|
||||
class C
|
||||
Const = :C
|
||||
def m
|
||||
eval('Const', TOPLEVEL_BINDING)
|
||||
end
|
||||
end
|
||||
C.new.m
|
||||
}
|
||||
ae %q{
|
||||
class C
|
||||
$b = binding
|
||||
end
|
||||
eval %q{
|
||||
def m
|
||||
:ok
|
||||
end
|
||||
}, $b
|
||||
p C.new.m
|
||||
}
|
||||
ae %q{
|
||||
b = proc{
|
||||
a = :ok
|
||||
binding
|
||||
}.call
|
||||
a = :ng
|
||||
eval("a", b)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
408
yarvtest/test_exception.rb
Normal file
408
yarvtest/test_exception.rb
Normal file
|
@ -0,0 +1,408 @@
|
|||
require 'yarvtest/yarvtest'
|
||||
|
||||
class TestException < YarvTestBase
|
||||
|
||||
def test_rescue
|
||||
ae %q{
|
||||
begin
|
||||
1
|
||||
rescue
|
||||
2
|
||||
end
|
||||
}
|
||||
|
||||
ae %q{
|
||||
begin
|
||||
1
|
||||
begin
|
||||
2
|
||||
rescue
|
||||
3
|
||||
end
|
||||
4
|
||||
rescue
|
||||
5
|
||||
end
|
||||
}
|
||||
|
||||
ae %q{
|
||||
begin
|
||||
1
|
||||
rescue
|
||||
2
|
||||
else
|
||||
3
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_ensure
|
||||
ae %q{
|
||||
begin
|
||||
1+1
|
||||
ensure
|
||||
2+2
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
begin
|
||||
1+1
|
||||
begin
|
||||
2+2
|
||||
ensure
|
||||
3+3
|
||||
end
|
||||
ensure
|
||||
4+4
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
begin
|
||||
1+1
|
||||
begin
|
||||
2+2
|
||||
ensure
|
||||
3+3
|
||||
end
|
||||
ensure
|
||||
4+4
|
||||
begin
|
||||
5+5
|
||||
ensure
|
||||
6+6
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_rescue_ensure
|
||||
ae %q{
|
||||
begin
|
||||
1+1
|
||||
rescue
|
||||
2+2
|
||||
ensure
|
||||
3+3
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
begin
|
||||
1+1
|
||||
rescue
|
||||
2+2
|
||||
ensure
|
||||
3+3
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
begin
|
||||
1+1
|
||||
rescue
|
||||
2+2
|
||||
else
|
||||
3+3
|
||||
ensure
|
||||
4+4
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
begin
|
||||
1+1
|
||||
begin
|
||||
2+2
|
||||
rescue
|
||||
3+3
|
||||
else
|
||||
4+4
|
||||
end
|
||||
rescue
|
||||
5+5
|
||||
else
|
||||
6+6
|
||||
ensure
|
||||
7+7
|
||||
end
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
def test_raise
|
||||
ae %q{
|
||||
begin
|
||||
raise
|
||||
rescue
|
||||
:ok
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
begin
|
||||
raise
|
||||
rescue
|
||||
:ok
|
||||
ensure
|
||||
:ng
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
begin
|
||||
raise
|
||||
rescue => e
|
||||
e.class
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
begin
|
||||
raise
|
||||
rescue StandardError
|
||||
:ng
|
||||
rescue Exception
|
||||
:ok
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
begin
|
||||
begin
|
||||
raise "a"
|
||||
rescue
|
||||
raise "b"
|
||||
ensure
|
||||
raise "c"
|
||||
end
|
||||
rescue => e
|
||||
e.message
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_error_variable
|
||||
ae %q{
|
||||
a = nil
|
||||
1.times{|e|
|
||||
begin
|
||||
rescue => err
|
||||
end
|
||||
a = err.class
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
a = nil
|
||||
1.times{|e|
|
||||
begin
|
||||
raise
|
||||
rescue => err
|
||||
end
|
||||
a = err.class
|
||||
}
|
||||
a
|
||||
}
|
||||
end
|
||||
|
||||
def test_raise_in_other_scope
|
||||
ae %q{
|
||||
class E1 < Exception
|
||||
end
|
||||
|
||||
def m
|
||||
yield
|
||||
end
|
||||
|
||||
begin
|
||||
begin
|
||||
begin
|
||||
m{
|
||||
raise
|
||||
}
|
||||
rescue E1
|
||||
:ok2
|
||||
ensure
|
||||
end
|
||||
rescue
|
||||
:ok3
|
||||
ensure
|
||||
end
|
||||
rescue E1
|
||||
:ok
|
||||
ensure
|
||||
end
|
||||
} do
|
||||
remove_const :E1
|
||||
end
|
||||
|
||||
ae %q{
|
||||
$i = 0
|
||||
def m
|
||||
iter{
|
||||
begin
|
||||
$i += 1
|
||||
begin
|
||||
$i += 2
|
||||
break
|
||||
ensure
|
||||
|
||||
end
|
||||
ensure
|
||||
$i += 4
|
||||
end
|
||||
$i = 0
|
||||
}
|
||||
end
|
||||
|
||||
def iter
|
||||
yield
|
||||
end
|
||||
m
|
||||
$i
|
||||
}
|
||||
|
||||
ae %q{
|
||||
$i = 0
|
||||
def m
|
||||
begin
|
||||
$i += 1
|
||||
begin
|
||||
$i += 2
|
||||
return
|
||||
ensure
|
||||
$i += 3
|
||||
end
|
||||
ensure
|
||||
$i += 4
|
||||
end
|
||||
p :end
|
||||
end
|
||||
m
|
||||
$i
|
||||
}
|
||||
end
|
||||
|
||||
def test_raise_in_cont_sp
|
||||
ae %q{
|
||||
def m a, b
|
||||
a + b
|
||||
end
|
||||
m(1, begin
|
||||
raise
|
||||
rescue
|
||||
2
|
||||
end) +
|
||||
m(10, begin
|
||||
raise
|
||||
rescue
|
||||
20
|
||||
ensure
|
||||
30
|
||||
end)
|
||||
}
|
||||
ae %q{
|
||||
def m a, b
|
||||
a + b
|
||||
end
|
||||
m(begin
|
||||
raise
|
||||
rescue
|
||||
1
|
||||
end,
|
||||
begin
|
||||
raise
|
||||
rescue
|
||||
2
|
||||
end)
|
||||
}
|
||||
end
|
||||
|
||||
def test_geterror
|
||||
ae %q{
|
||||
$!
|
||||
}
|
||||
ae %q{
|
||||
begin
|
||||
raise "FOO"
|
||||
rescue
|
||||
$!
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
def m
|
||||
$!
|
||||
end
|
||||
begin
|
||||
raise "FOO"
|
||||
rescue
|
||||
m()
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
$ans = []
|
||||
def m
|
||||
$!
|
||||
end
|
||||
begin
|
||||
raise "FOO"
|
||||
rescue
|
||||
begin
|
||||
raise "BAR"
|
||||
rescue
|
||||
$ans << m()
|
||||
end
|
||||
$ans << m()
|
||||
end
|
||||
$ans
|
||||
}
|
||||
ae %q{
|
||||
$ans = []
|
||||
def m
|
||||
$!
|
||||
end
|
||||
|
||||
begin
|
||||
begin
|
||||
raise "FOO"
|
||||
ensure
|
||||
$ans << m()
|
||||
end
|
||||
rescue
|
||||
$ans << m()
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
$ans = []
|
||||
def m
|
||||
$!
|
||||
end
|
||||
def m2
|
||||
1.times{
|
||||
begin
|
||||
return
|
||||
ensure
|
||||
$ans << m
|
||||
end
|
||||
}
|
||||
end
|
||||
m2
|
||||
$ans
|
||||
}
|
||||
end
|
||||
|
||||
def test_stack_consistency
|
||||
ae %q{ #
|
||||
proc{
|
||||
begin
|
||||
raise
|
||||
break
|
||||
rescue
|
||||
:ok
|
||||
end
|
||||
}.call
|
||||
}
|
||||
ae %q{
|
||||
proc do
|
||||
begin
|
||||
raise StandardError
|
||||
redo
|
||||
rescue StandardError
|
||||
end
|
||||
end.call
|
||||
}
|
||||
end
|
||||
end
|
||||
|
591
yarvtest/test_flow.rb
Normal file
591
yarvtest/test_flow.rb
Normal file
|
@ -0,0 +1,591 @@
|
|||
#
|
||||
# This test program is contributed by George Marrows
|
||||
# Re: [Yarv-devel] Some tests for test_jump.rb
|
||||
#
|
||||
|
||||
require 'yarvtest/yarvtest'
|
||||
|
||||
class TestFlow < YarvTestBase
|
||||
def ae_flow(src, for_value=true)
|
||||
# Tracks flow through the code
|
||||
# A test like
|
||||
# begin
|
||||
# ensure
|
||||
# end
|
||||
# gets transformed into
|
||||
# a = []
|
||||
# begin
|
||||
# begin; a << 1
|
||||
# ensure; a << 2
|
||||
# end; a << 3
|
||||
# rescue Exception
|
||||
# a << 99
|
||||
# end
|
||||
# a
|
||||
# before being run. This tracks control flow through the code.
|
||||
|
||||
cnt = 0
|
||||
src = src.gsub(/(\n|$)/) { "; $a << #{cnt+=1}\n" }
|
||||
src = "$a = []; begin; #{src}; rescue Exception; $a << 99; end; $a"
|
||||
|
||||
if false#||true
|
||||
STDERR.puts
|
||||
STDERR.puts '#----'
|
||||
STDERR.puts src
|
||||
STDERR.puts '#----'
|
||||
end
|
||||
|
||||
ae(src)
|
||||
end
|
||||
|
||||
def test_while_with_ensure
|
||||
ae %q{
|
||||
a = []
|
||||
i = 0
|
||||
begin
|
||||
while i < 1
|
||||
i+=1
|
||||
begin
|
||||
begin
|
||||
next
|
||||
ensure
|
||||
a << :ok
|
||||
end
|
||||
ensure
|
||||
a << :ok2
|
||||
end
|
||||
end
|
||||
ensure
|
||||
a << :last
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
a = []
|
||||
i = 0
|
||||
begin
|
||||
while i < 1
|
||||
i+=1
|
||||
begin
|
||||
begin
|
||||
break
|
||||
ensure
|
||||
a << :ok
|
||||
end
|
||||
ensure
|
||||
a << :ok2
|
||||
end
|
||||
end
|
||||
ensure
|
||||
a << :last
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
a = []
|
||||
i = 0
|
||||
begin
|
||||
while i < 1
|
||||
if i>0
|
||||
break
|
||||
end
|
||||
i+=1
|
||||
begin
|
||||
begin
|
||||
redo
|
||||
ensure
|
||||
a << :ok
|
||||
end
|
||||
ensure
|
||||
a << :ok2
|
||||
end
|
||||
end
|
||||
ensure
|
||||
a << :last
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_ensure_normal_flow
|
||||
ae_flow %{
|
||||
begin
|
||||
ensure
|
||||
end }
|
||||
end
|
||||
|
||||
def test_ensure_exception
|
||||
ae_flow %{
|
||||
begin
|
||||
raise StandardError
|
||||
ensure
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_break_in_block_runs_ensure
|
||||
ae_flow %{
|
||||
[1,2].each do
|
||||
begin
|
||||
break
|
||||
ensure
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_next_in_block_runs_ensure
|
||||
ae_flow %{
|
||||
[1,2].each do
|
||||
begin
|
||||
next
|
||||
ensure
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
def test_return_from_method_runs_ensure
|
||||
ae_flow %{
|
||||
o = "test"
|
||||
def o.test(a)
|
||||
return a
|
||||
ensure
|
||||
end
|
||||
o.test(123)
|
||||
}
|
||||
end
|
||||
|
||||
def test_break_from_ifunc
|
||||
ae %q{
|
||||
["a"].inject("ng"){|x,y|
|
||||
break :ok
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
unless ''.respond_to? :lines
|
||||
class String
|
||||
def lines
|
||||
self
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
('a').lines.map{|e|
|
||||
break :ok
|
||||
}
|
||||
}
|
||||
ae_flow %q{
|
||||
["a"].inject("ng"){|x,y|
|
||||
break :ok
|
||||
}
|
||||
}
|
||||
ae_flow %q{
|
||||
('a'..'b').map{|e|
|
||||
break :ok
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_break_ensure_interaction1
|
||||
# make sure that any 'break state' set up in the VM is c
|
||||
# the time of the ensure
|
||||
ae_flow %{
|
||||
[1,2].each{
|
||||
break
|
||||
}
|
||||
begin
|
||||
ensure
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_break_ensure_interaction2
|
||||
# ditto, different arrangement
|
||||
ae_flow %{
|
||||
begin
|
||||
[1,2].each do
|
||||
break
|
||||
end
|
||||
ensure
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_break_through_2_ensures
|
||||
ae_flow %{
|
||||
[1,2].each do
|
||||
begin
|
||||
begin
|
||||
break
|
||||
ensure
|
||||
end
|
||||
ensure
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_ensure_break_ensure
|
||||
# break through an ensure; run 2nd normally
|
||||
ae_flow %{
|
||||
begin
|
||||
[1,2].each do
|
||||
begin
|
||||
break
|
||||
ensure
|
||||
end
|
||||
end
|
||||
ensure
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_exception_overrides_break
|
||||
ae_flow %{
|
||||
[1,2].each do
|
||||
begin
|
||||
break
|
||||
ensure
|
||||
raise StandardError
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_break_overrides_exception
|
||||
ae_flow %{
|
||||
[1,2].each do
|
||||
begin
|
||||
raise StandardError
|
||||
ensure
|
||||
break
|
||||
end
|
||||
end
|
||||
}
|
||||
ae_flow %{
|
||||
[1,2].each do
|
||||
begin
|
||||
raise StandardError
|
||||
rescue
|
||||
break
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_break_in_exception
|
||||
ae_flow %q{
|
||||
i=0
|
||||
while i<3
|
||||
i+=1
|
||||
begin
|
||||
ensure
|
||||
break
|
||||
end
|
||||
end
|
||||
}
|
||||
ae_flow %q{
|
||||
i=0
|
||||
while i<3
|
||||
i+=1
|
||||
begin
|
||||
raise
|
||||
ensure
|
||||
break
|
||||
end
|
||||
end
|
||||
}
|
||||
ae_flow %q{
|
||||
i=0
|
||||
while i<3
|
||||
i+=1
|
||||
begin
|
||||
raise
|
||||
rescue
|
||||
break
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_next_in_exception
|
||||
return
|
||||
ae_flow %q{
|
||||
i=0
|
||||
while i<3
|
||||
i+=1
|
||||
begin
|
||||
ensure
|
||||
next
|
||||
end
|
||||
end
|
||||
}
|
||||
ae_flow %q{
|
||||
i=0
|
||||
while i<3
|
||||
i+=1
|
||||
begin
|
||||
raise
|
||||
ensure
|
||||
next
|
||||
end
|
||||
end
|
||||
}
|
||||
ae_flow %q{
|
||||
i=0
|
||||
while i<3
|
||||
i+=1
|
||||
begin
|
||||
raise
|
||||
rescue
|
||||
next
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_complex_break
|
||||
ae_flow %q{
|
||||
i = 0
|
||||
while i<3
|
||||
i+=1
|
||||
j = 0
|
||||
while j<3
|
||||
j+=1
|
||||
begin
|
||||
raise
|
||||
rescue
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
ae_flow %q{
|
||||
i = 0
|
||||
while i<3
|
||||
i+=1
|
||||
j = 0
|
||||
while j<3
|
||||
j+=1
|
||||
1.times{
|
||||
begin
|
||||
raise
|
||||
rescue
|
||||
break
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
}
|
||||
ae_flow %q{
|
||||
i = 0
|
||||
while i<3
|
||||
i+=1
|
||||
j = 0
|
||||
while j<3
|
||||
j+=1
|
||||
begin
|
||||
raise
|
||||
ensure
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
ae_flow %q{
|
||||
i = 0
|
||||
while i<3
|
||||
i+=1
|
||||
j = 0
|
||||
while j<3
|
||||
j+=1
|
||||
1.times{
|
||||
begin
|
||||
raise
|
||||
ensure
|
||||
break
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
}
|
||||
ae_flow %q{
|
||||
while true
|
||||
begin
|
||||
break
|
||||
ensure
|
||||
break
|
||||
end
|
||||
end
|
||||
}
|
||||
ae_flow %q{
|
||||
while true
|
||||
begin
|
||||
break
|
||||
ensure
|
||||
raise
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_jump_from_class
|
||||
ae_flow %q{
|
||||
3.times{
|
||||
class C
|
||||
break
|
||||
end
|
||||
}
|
||||
}
|
||||
ae_flow %q{
|
||||
3.times{
|
||||
class A
|
||||
class B
|
||||
break
|
||||
end
|
||||
end
|
||||
}
|
||||
}
|
||||
ae_flow %q{
|
||||
3.times{
|
||||
class C
|
||||
next
|
||||
end
|
||||
}
|
||||
}
|
||||
ae_flow %q{
|
||||
3.times{
|
||||
class C
|
||||
class D
|
||||
next
|
||||
end
|
||||
end
|
||||
}
|
||||
}
|
||||
ae_flow %q{
|
||||
while true
|
||||
class C
|
||||
break
|
||||
end
|
||||
end
|
||||
}
|
||||
ae_flow %q{
|
||||
while true
|
||||
class C
|
||||
class D
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
ae_flow %q{
|
||||
i=0
|
||||
while i<3
|
||||
i+=1
|
||||
class C
|
||||
next 10
|
||||
end
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
1.times{
|
||||
while true
|
||||
class C
|
||||
begin
|
||||
break
|
||||
ensure
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_flow_with_cont_sp
|
||||
ae %q{
|
||||
def m a, b
|
||||
a + b
|
||||
end
|
||||
m(1,
|
||||
while true
|
||||
break 2
|
||||
end
|
||||
)
|
||||
}
|
||||
ae %q{
|
||||
def m a, b
|
||||
a + b
|
||||
end
|
||||
m(1,
|
||||
(i=0; while i<2
|
||||
i+=1
|
||||
class C
|
||||
next 2
|
||||
end
|
||||
end; 3)
|
||||
)
|
||||
}
|
||||
ae %q{
|
||||
def m a, b
|
||||
a+b
|
||||
end
|
||||
m(1, 1.times{break 3}) +
|
||||
m(10, (1.times{next 3}; 20))
|
||||
}
|
||||
end
|
||||
|
||||
def test_return_in_deep_stack
|
||||
ae_flow %q{
|
||||
def m1 *args
|
||||
|
||||
end
|
||||
def m2
|
||||
m1(:a, :b, (return 1; :c))
|
||||
end
|
||||
m2
|
||||
}
|
||||
end
|
||||
|
||||
def test_return_in_ensure
|
||||
ae_flow %q{
|
||||
def m()
|
||||
begin
|
||||
2
|
||||
ensure
|
||||
return 3
|
||||
end
|
||||
end
|
||||
m
|
||||
}
|
||||
ae_flow %q{
|
||||
def m2
|
||||
end
|
||||
def m()
|
||||
m2(begin
|
||||
2
|
||||
ensure
|
||||
return 3
|
||||
end)
|
||||
4
|
||||
end
|
||||
m()
|
||||
}
|
||||
ae_flow %q{
|
||||
def m
|
||||
1
|
||||
1.times{
|
||||
2
|
||||
begin
|
||||
3
|
||||
return
|
||||
4
|
||||
ensure
|
||||
5
|
||||
end
|
||||
6
|
||||
}
|
||||
7
|
||||
end
|
||||
m()
|
||||
}
|
||||
end
|
||||
end
|
||||
|
296
yarvtest/test_jump.rb
Normal file
296
yarvtest/test_jump.rb
Normal file
|
@ -0,0 +1,296 @@
|
|||
require 'yarvtest/yarvtest'
|
||||
|
||||
class TestJump < YarvTestBase
|
||||
|
||||
def test_redo
|
||||
ae %q{
|
||||
def m
|
||||
yield + 10
|
||||
end
|
||||
i=0
|
||||
m{
|
||||
if i>10
|
||||
i*i
|
||||
else
|
||||
i+=1
|
||||
redo
|
||||
end
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_next
|
||||
ae %q{
|
||||
def m
|
||||
yield
|
||||
:ok
|
||||
end
|
||||
i=0
|
||||
m{
|
||||
if i>10
|
||||
i*i
|
||||
else
|
||||
i+=1
|
||||
next
|
||||
end
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_next_with_val
|
||||
ae %q{
|
||||
def m
|
||||
yield
|
||||
end
|
||||
|
||||
m{
|
||||
next :ok
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_return
|
||||
ae %q{
|
||||
def m
|
||||
return 3
|
||||
end
|
||||
m
|
||||
}
|
||||
|
||||
ae %q{
|
||||
def m
|
||||
:ng1
|
||||
mm{
|
||||
return :ok
|
||||
}
|
||||
:ng2
|
||||
end
|
||||
|
||||
def mm
|
||||
:ng3
|
||||
yield
|
||||
:ng4
|
||||
end
|
||||
m
|
||||
}
|
||||
end
|
||||
|
||||
def test_return2
|
||||
ae %q{
|
||||
$i = 0
|
||||
def m
|
||||
begin
|
||||
iter{
|
||||
return
|
||||
}
|
||||
ensure
|
||||
$i = 100
|
||||
end
|
||||
end
|
||||
|
||||
def iter
|
||||
yield
|
||||
end
|
||||
m
|
||||
$i
|
||||
}
|
||||
end
|
||||
|
||||
def test_return3
|
||||
ae %q{
|
||||
def m
|
||||
begin
|
||||
raise
|
||||
rescue
|
||||
return :ok
|
||||
end
|
||||
:ng
|
||||
end
|
||||
m
|
||||
}
|
||||
end
|
||||
|
||||
def test_break
|
||||
ae %q{
|
||||
def m
|
||||
:ng1
|
||||
mm{
|
||||
yield
|
||||
}
|
||||
:ng2
|
||||
end
|
||||
|
||||
def mm
|
||||
:ng3
|
||||
yield
|
||||
:ng4
|
||||
end
|
||||
|
||||
m{
|
||||
break :ok
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_exception_and_break
|
||||
ae %q{
|
||||
def m
|
||||
yield
|
||||
end
|
||||
|
||||
m{
|
||||
begin
|
||||
ensure
|
||||
break :ok
|
||||
end
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_retry
|
||||
# this test can't run on ruby 1.9(yarv can do)
|
||||
%q{
|
||||
def m a
|
||||
mm{
|
||||
yield
|
||||
}
|
||||
end
|
||||
|
||||
def mm
|
||||
yield
|
||||
end
|
||||
|
||||
i=0
|
||||
m(i+=1){
|
||||
retry if i<10
|
||||
:ok
|
||||
}
|
||||
}
|
||||
|
||||
ae %q{
|
||||
def m a
|
||||
yield
|
||||
end
|
||||
|
||||
i=0
|
||||
m(i+=1){
|
||||
retry if i<10
|
||||
:ok
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_complex_jump
|
||||
ae %q{
|
||||
module Enumerable
|
||||
def all_?
|
||||
self.each{|e|
|
||||
unless yield(e)
|
||||
return false
|
||||
end
|
||||
}
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
xxx = 0
|
||||
[1,2].each{|bi|
|
||||
[3,4].each{|bj|
|
||||
[true, nil, true].all_?{|be| be}
|
||||
break
|
||||
}
|
||||
xxx += 1
|
||||
}
|
||||
xxx
|
||||
}
|
||||
end
|
||||
|
||||
def test_return_from
|
||||
ae %q{
|
||||
def m
|
||||
begin
|
||||
raise
|
||||
rescue
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
m
|
||||
}
|
||||
ae %q{
|
||||
def m
|
||||
begin
|
||||
#
|
||||
ensure
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
m
|
||||
}
|
||||
end
|
||||
|
||||
def test_break_from_times
|
||||
ae %q{
|
||||
3.times{
|
||||
break :ok
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_catch_and_throw
|
||||
ae %q{
|
||||
catch(:foo){
|
||||
throw :foo
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
catch(:foo){
|
||||
throw :foo, false
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
catch(:foo){
|
||||
throw :foo, nil
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
catch(:foo){
|
||||
throw :foo, :ok
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
catch(:foo){
|
||||
1.times{
|
||||
throw :foo
|
||||
}
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
catch(:foo){
|
||||
1.times{
|
||||
throw :foo, :ok
|
||||
}
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
catch(:foo){
|
||||
catch(:bar){
|
||||
throw :foo, :ok
|
||||
}
|
||||
:ng
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
catch(:foo){
|
||||
catch(:bar){
|
||||
1.times{
|
||||
throw :foo, :ok
|
||||
}
|
||||
}
|
||||
:ng
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
417
yarvtest/test_massign.rb
Normal file
417
yarvtest/test_massign.rb
Normal file
|
@ -0,0 +1,417 @@
|
|||
require 'yarvtest/yarvtest'
|
||||
|
||||
# test of syntax
|
||||
class TestMassign < YarvTestBase
|
||||
def test_simle
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
x, y = a, b
|
||||
[x, y]
|
||||
}
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
x, y, z = a, b, c
|
||||
[x, y, z]
|
||||
}
|
||||
end
|
||||
|
||||
def test_diff_elems
|
||||
ae %q{
|
||||
a = :a ; b = :b ; c = :c
|
||||
x, y, z = a, b
|
||||
[x, y, z]
|
||||
}
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
x, y = a, b, c
|
||||
[x, y]
|
||||
}
|
||||
end
|
||||
|
||||
def test_single_l
|
||||
ae %q{
|
||||
a = :a; b = :b
|
||||
x = a, b
|
||||
x
|
||||
}
|
||||
ae %q{
|
||||
a = [1, 2]; b = [3, 4]
|
||||
x = a, b
|
||||
x
|
||||
}
|
||||
end
|
||||
|
||||
def test_single_r
|
||||
ae %q{
|
||||
a = :a
|
||||
x, y = a
|
||||
[x, y]
|
||||
}
|
||||
ae %q{
|
||||
a = [1, 2]
|
||||
x, y = a
|
||||
[x, y]
|
||||
}
|
||||
ae %q{
|
||||
a = [1, 2, 3]
|
||||
x, y = a
|
||||
[x, y]
|
||||
}
|
||||
end
|
||||
|
||||
def test_splat_l
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
*x = a, b
|
||||
[x]
|
||||
}
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
*x = a, b
|
||||
[x]
|
||||
}
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
x, * = a, b
|
||||
[x]
|
||||
}
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
x, *y = a, b
|
||||
[x, y]
|
||||
}
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
x, y, *z = a, b
|
||||
[x, y]
|
||||
}
|
||||
ae %q{ # only one item on rhs
|
||||
*x = :x
|
||||
x
|
||||
}
|
||||
ae %q{ # nil on rhs
|
||||
*x = nil
|
||||
x
|
||||
}
|
||||
end
|
||||
|
||||
def test_splat_r
|
||||
if false
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
x, y = *a
|
||||
[x, y]
|
||||
}
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
x, y = a, *b
|
||||
[x, y]
|
||||
}
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
x, y = a, b, *c
|
||||
[x, y]
|
||||
}
|
||||
ae %q{
|
||||
x=*nil
|
||||
x
|
||||
}
|
||||
end
|
||||
|
||||
ae %q{
|
||||
a = [:a, :a2]; b = [:b, :b2]; c = [:c, :c2]
|
||||
x, y = *a
|
||||
[x, y]
|
||||
}
|
||||
ae %q{
|
||||
a = [:a, :a2]; b = [:b, :b2]; c = [:c, :c2]
|
||||
x, y = a, *b
|
||||
[x, y]
|
||||
}
|
||||
ae %q{
|
||||
a = [:a, :a2]; b = [:b, :b2]; c = [:c, :c2]
|
||||
x, y = a, b, *c
|
||||
[x, y]
|
||||
}
|
||||
end
|
||||
|
||||
def test_splat_b1
|
||||
if false
|
||||
# error
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
x, *y = *a
|
||||
[x, y]
|
||||
}
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
x, *y = a, *b
|
||||
[x, y]
|
||||
}
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
x, *y = a, b, *c
|
||||
[x, y]
|
||||
}
|
||||
end
|
||||
|
||||
ae %q{
|
||||
a = [:a, :a2]; b = [:b, :b2]; c = [:c, :c2]
|
||||
x, *y = *a
|
||||
[x, y]
|
||||
}
|
||||
ae %q{
|
||||
a = [:a, :a2]; b = [:b, :b2]; c = [:c, :c2]
|
||||
x, *y = a, *b
|
||||
[x, y]
|
||||
}
|
||||
ae %q{
|
||||
a = [:a, :a2]; b = [:b, :b2]; c = [:c, :c2]
|
||||
x, *y = a, b, *c
|
||||
[x, y]
|
||||
}
|
||||
end
|
||||
|
||||
def test_splat_b2
|
||||
if false
|
||||
# error
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
*x = *a
|
||||
x
|
||||
}
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
*x = a, *b
|
||||
x
|
||||
}
|
||||
ae %q{
|
||||
a = :a; b = :b; c = :c
|
||||
*x = a, b, *c
|
||||
x
|
||||
}
|
||||
end
|
||||
|
||||
ae %q{
|
||||
a = [:a, :a2]; b = [:b, :b2]; c = [:c, :c2]
|
||||
*x = *a
|
||||
x
|
||||
}
|
||||
ae %q{
|
||||
a = [:a, :a2]; b = [:b, :b2]; c = [:c, :c2]
|
||||
*x = a, *b
|
||||
x
|
||||
}
|
||||
ae %q{
|
||||
a = [:a, :a2]; b = [:b, :b2]; c = [:c, :c2]
|
||||
*x = a, b, *c
|
||||
x
|
||||
}
|
||||
end
|
||||
|
||||
def test_toary
|
||||
ae %q{
|
||||
x, y = :a
|
||||
[x, y]
|
||||
}
|
||||
ae %q{
|
||||
x, y = [1, 2]
|
||||
[x, y]
|
||||
}
|
||||
ae %q{
|
||||
x, y = [1, 2, 3]
|
||||
[x, y]
|
||||
}
|
||||
end
|
||||
|
||||
def test_swap
|
||||
ae %q{
|
||||
a = 1; b = 2
|
||||
a, b = b, a
|
||||
[a, b]
|
||||
}
|
||||
end
|
||||
|
||||
def test_mret
|
||||
ae %q{
|
||||
def m
|
||||
return 1, 2
|
||||
end
|
||||
|
||||
a, b = m
|
||||
[a, b]
|
||||
}
|
||||
ae %q{
|
||||
def m
|
||||
return 1, 2
|
||||
end
|
||||
|
||||
a = m
|
||||
[a]
|
||||
}
|
||||
ae %q{
|
||||
def m
|
||||
return 1
|
||||
end
|
||||
|
||||
a, b = m
|
||||
[a, b]
|
||||
}
|
||||
end
|
||||
|
||||
def test_mret_splat
|
||||
if false
|
||||
ae %q{
|
||||
def m
|
||||
return *1
|
||||
end
|
||||
a, b = m
|
||||
[a, b]
|
||||
}
|
||||
end
|
||||
|
||||
ae %q{
|
||||
def m
|
||||
return *[]
|
||||
end
|
||||
a, b = m
|
||||
[a, b]
|
||||
}
|
||||
ae %q{
|
||||
def m
|
||||
return *[1]
|
||||
end
|
||||
a, b = m
|
||||
[a, b]
|
||||
}
|
||||
ae %q{
|
||||
def m
|
||||
return *[1,2]
|
||||
end
|
||||
a, b = m
|
||||
[a, b]
|
||||
}
|
||||
ae %q{
|
||||
def m
|
||||
return *[1,2,3]
|
||||
end
|
||||
a, b = m
|
||||
[a, b]
|
||||
}
|
||||
ae %q{
|
||||
def m
|
||||
return *[1]
|
||||
end
|
||||
a = m
|
||||
}
|
||||
end
|
||||
|
||||
def test_mret_argscat
|
||||
ae %q{
|
||||
def m
|
||||
return 1, *[]
|
||||
end
|
||||
a, b = m
|
||||
[a, b]
|
||||
}
|
||||
ae %q{
|
||||
def m
|
||||
return 1, 2, *[1]
|
||||
end
|
||||
a, b = m
|
||||
[a, b]
|
||||
}
|
||||
ae %q{
|
||||
def m
|
||||
return 1, 2, 3, *[1,2]
|
||||
end
|
||||
a, b = m
|
||||
[a, b]
|
||||
}
|
||||
end
|
||||
|
||||
def test_nested_massign
|
||||
ae %q{
|
||||
(a, b), c = [[1, 2], 3]
|
||||
[a, b, c]
|
||||
}
|
||||
ae %q{
|
||||
a, (b, c) = [[1, 2], 3]
|
||||
[a, b, c]
|
||||
}
|
||||
ae %q{
|
||||
a, (b, c) = [1, [2, 3]]
|
||||
[a, b, c]
|
||||
}
|
||||
ae %q{
|
||||
(a, b), *c = [[1, 2], 3]
|
||||
[a, b, c]
|
||||
}
|
||||
ae %q{
|
||||
(a, b), c, (d, e) = [[1, 2], 3, [4, 5]]
|
||||
[a, b, c, d, e]
|
||||
}
|
||||
ae %q{
|
||||
(a, *b), c, (d, e, *) = [[1, 2], 3, [4, 5]]
|
||||
[a, b, c, d, e]
|
||||
}
|
||||
ae %q{
|
||||
(a, b), c, (d, *e) = [[1, 2, 3], 3, [4, 5, 6, 7]]
|
||||
[a, b, c, d, e]
|
||||
}
|
||||
ae %q{
|
||||
(a, (b1, b2)), c, (d, e) = [[1, 2], 3, [4, 5]]
|
||||
[a, b1, b2, c, d, e]
|
||||
}
|
||||
ae %q{
|
||||
(a, (b1, b2)), c, (d, e) = [[1, [21, 22]], 3, [4, 5]]
|
||||
[a, b1, b2, c, d, e]
|
||||
}
|
||||
end
|
||||
|
||||
# ignore
|
||||
def _test_massign_value
|
||||
# Value of this massign statement should be [1, 2, 3]
|
||||
ae %q{
|
||||
a, b, c = [1, 2, 3]
|
||||
}
|
||||
end
|
||||
|
||||
def test_nested_splat
|
||||
# Somewhat obscure nested splat
|
||||
ae %q{
|
||||
a = *[*[1]]
|
||||
a
|
||||
}
|
||||
end
|
||||
|
||||
def test_calls_to_a
|
||||
# Should be result of calling to_a on arg, ie [[1, 2], [3, 4]]
|
||||
ae %q{
|
||||
x=*{1=>2,3=>4}
|
||||
x
|
||||
}
|
||||
end
|
||||
|
||||
def test_const_massign
|
||||
ae %q{
|
||||
class C
|
||||
class D
|
||||
end
|
||||
end
|
||||
|
||||
X, Y = 1, 2
|
||||
Z, C::Const, C::D::Const, ::C::Const2 = 3, 4, 5, 6
|
||||
[X, Y, Z, C::Const, C::D::Const, ::C::Const2]
|
||||
}
|
||||
end
|
||||
|
||||
def test_massign_values
|
||||
ae %q{
|
||||
ary = [1, 2].partition {|n| n == 1 }
|
||||
a, b = ary
|
||||
[a, b]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
539
yarvtest/test_method.rb
Normal file
539
yarvtest/test_method.rb
Normal file
|
@ -0,0 +1,539 @@
|
|||
require 'yarvtest/yarvtest'
|
||||
class TestMethod < YarvTestBase
|
||||
|
||||
def test_simple_method
|
||||
ae %q{
|
||||
def m_simple_method
|
||||
1
|
||||
end
|
||||
m_simple_method()
|
||||
}
|
||||
end
|
||||
|
||||
def test_polymorphic
|
||||
ae %q{
|
||||
o1 = 'str'
|
||||
o2 = 1
|
||||
str = ''
|
||||
i = 1
|
||||
while i<10
|
||||
i+=1
|
||||
o = (i%2==0) ? o1 : o2
|
||||
str += o.to_s
|
||||
end
|
||||
str
|
||||
}
|
||||
end
|
||||
|
||||
def test_arg
|
||||
ae <<-'EOS'
|
||||
def m_arg(a1, a2)
|
||||
a1+a2
|
||||
end
|
||||
m_arg(1,2)
|
||||
EOS
|
||||
end
|
||||
|
||||
def test_rec
|
||||
ae <<-'EOS'
|
||||
def m_rec n
|
||||
if n > 1
|
||||
n + m_rec(n-1)
|
||||
else
|
||||
1
|
||||
end
|
||||
end
|
||||
m_rec(10)
|
||||
EOS
|
||||
end
|
||||
|
||||
def test_splat
|
||||
ae %q{
|
||||
def m a
|
||||
a
|
||||
end
|
||||
begin
|
||||
m(*1)
|
||||
rescue TypeError
|
||||
:ok
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
def m a, b
|
||||
[a, b]
|
||||
end
|
||||
m(*[1,2])
|
||||
}
|
||||
ae %q{
|
||||
def m a, b, c
|
||||
[a, b, c]
|
||||
end
|
||||
m(1, *[2, 3])
|
||||
}
|
||||
|
||||
ae %q{
|
||||
def m a, b, c
|
||||
[a, b, c]
|
||||
end
|
||||
|
||||
m(1, 2, *[3])
|
||||
}
|
||||
end
|
||||
|
||||
def test_rest
|
||||
ae %q{
|
||||
def m *a
|
||||
a
|
||||
end
|
||||
|
||||
m
|
||||
}
|
||||
|
||||
ae %q{
|
||||
def m *a
|
||||
a
|
||||
end
|
||||
|
||||
m 1
|
||||
}
|
||||
|
||||
ae %q{
|
||||
def m *a
|
||||
a
|
||||
end
|
||||
|
||||
m 1, 2, 3
|
||||
}
|
||||
|
||||
ae %q{
|
||||
def m x, *a
|
||||
[x, a]
|
||||
end
|
||||
|
||||
m 1
|
||||
}
|
||||
|
||||
ae %q{
|
||||
def m x, *a
|
||||
[x, a]
|
||||
end
|
||||
|
||||
m 1, 2
|
||||
}
|
||||
|
||||
ae %q{
|
||||
def m x, *a
|
||||
[x, a]
|
||||
end
|
||||
|
||||
m 1, 2, 3, 4
|
||||
}
|
||||
end
|
||||
|
||||
def test_opt
|
||||
ae %q{
|
||||
def m a=1
|
||||
a
|
||||
end
|
||||
m
|
||||
}
|
||||
ae %q{
|
||||
def m a=1
|
||||
a
|
||||
end
|
||||
m 2
|
||||
}
|
||||
ae %q{
|
||||
def m a=1, b=2
|
||||
[a, b]
|
||||
end
|
||||
m
|
||||
}
|
||||
ae %q{
|
||||
def m a=1, b=2
|
||||
[a, b]
|
||||
end
|
||||
m 10
|
||||
}
|
||||
ae %q{
|
||||
def m a=1, b=2
|
||||
[a, b]
|
||||
end
|
||||
m 10, 20
|
||||
}
|
||||
ae %q{
|
||||
def m x, a=1, b=2
|
||||
[x, a, b]
|
||||
end
|
||||
m 10
|
||||
}
|
||||
ae %q{
|
||||
def m x, a=1, b=2
|
||||
[x, a, b]
|
||||
end
|
||||
m 10, 20
|
||||
}
|
||||
ae %q{
|
||||
def m x, a=1, b=2
|
||||
[x, a, b]
|
||||
end
|
||||
m 10, 20, 30
|
||||
}
|
||||
ae %q{
|
||||
def m x, y, a
|
||||
[x, y, a]
|
||||
end
|
||||
m 10, 20, 30
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
def test_opt_rest
|
||||
ae %q{
|
||||
def m0 b = 0, c = 1, *d
|
||||
[:sep, b, c, d]
|
||||
end
|
||||
|
||||
def m1 a, b = 0, c = 1, *d
|
||||
[:sep, a, b, c, d]
|
||||
end
|
||||
|
||||
def m2 x, a, b = 0, c = 1, *d
|
||||
[:sep, x, a, b, c, d]
|
||||
end
|
||||
|
||||
def m3 x, y, a, b = 0, c = 1, *d
|
||||
[:sep, x, y, a, b, c, d]
|
||||
end
|
||||
|
||||
def s3 x, y, a, b = 0, c = 1
|
||||
[:sep, x, y, a, b, c]
|
||||
end
|
||||
|
||||
m0() +
|
||||
m0(:a) +
|
||||
m0(:a, :b) +
|
||||
m0(:a, :b, :c) +
|
||||
m0(:a, :b, :c, :d) +
|
||||
m0(:a, :b, :c, :d, :e) +
|
||||
m1(:a) +
|
||||
m1(:a, :b) +
|
||||
m1(:a, :b, :c) +
|
||||
m1(:a, :b, :c, :d) +
|
||||
m1(:a, :b, :c, :d, :e) +
|
||||
m2(:a, :b) +
|
||||
m2(:a, :b, :c) +
|
||||
m2(:a, :b, :c, :d) +
|
||||
m2(:a, :b, :c, :d, :e) +
|
||||
m2(:a, :b, :c, :d, :e, :f) +
|
||||
m3(:a, :b, :c) +
|
||||
m3(:a, :b, :c, :d) +
|
||||
m3(:a, :b, :c, :d, :e) +
|
||||
m3(:a, :b, :c, :d, :e, :f) +
|
||||
m3(:a, :b, :c, :d, :e, :f, :g)
|
||||
}
|
||||
end
|
||||
|
||||
def test_opt_rest_block
|
||||
ae %q{
|
||||
def m a, b = 0, c = 1, *d, &pr
|
||||
[a, b, c, d, pr]
|
||||
end
|
||||
m(:a) +
|
||||
m(:a, :b) +
|
||||
m(:a, :b, :c) +
|
||||
m(:a, :b, :c, :d) +
|
||||
m(:a, :b, :c, :d, :e)
|
||||
}
|
||||
ae %q{
|
||||
def m a, b = 0, c = 1, *d, &pr
|
||||
[a, b, c, d, pr.call]
|
||||
end
|
||||
|
||||
m(:a){1} +
|
||||
m(:a, :b){2} +
|
||||
m(:a, :b, :c){3} +
|
||||
m(:a, :b, :c, :d){4} +
|
||||
m(:a, :b, :c, :d, :e){5}
|
||||
}
|
||||
end
|
||||
|
||||
def test_singletonmethod
|
||||
ae %q{
|
||||
lobj = Object.new
|
||||
def lobj.m
|
||||
:singleton
|
||||
end
|
||||
lobj.m
|
||||
}
|
||||
ae %q{
|
||||
class C
|
||||
def m
|
||||
:C_m
|
||||
end
|
||||
end
|
||||
lobj = C.new
|
||||
def lobj.m
|
||||
:Singleton_m
|
||||
end
|
||||
lobj.m
|
||||
}
|
||||
end
|
||||
|
||||
def test_singletonmethod_with_const
|
||||
ae %q{
|
||||
class C
|
||||
Const = :C
|
||||
def self.m
|
||||
1.times{
|
||||
Const
|
||||
}
|
||||
end
|
||||
end
|
||||
C.m
|
||||
}
|
||||
end
|
||||
|
||||
def test_alias
|
||||
ae %q{
|
||||
def m1
|
||||
:ok
|
||||
end
|
||||
alias :m2 :m1
|
||||
m1
|
||||
}
|
||||
ae %q{
|
||||
def m1
|
||||
:ok
|
||||
end
|
||||
alias m2 m1
|
||||
m1
|
||||
}
|
||||
ae %q{
|
||||
def m1
|
||||
:ok
|
||||
end
|
||||
alias m2 :m1
|
||||
m1
|
||||
}
|
||||
ae %q{
|
||||
def m1
|
||||
:ok
|
||||
end
|
||||
alias :m2 m1
|
||||
m1
|
||||
}
|
||||
ae %q{
|
||||
def m1
|
||||
:ok
|
||||
end
|
||||
alias m2 m1
|
||||
def m1
|
||||
:ok2
|
||||
end
|
||||
[m1, m2]
|
||||
}
|
||||
end
|
||||
|
||||
def test_split
|
||||
ae %q{
|
||||
'abc'.split(/b/)
|
||||
}
|
||||
ae %q{
|
||||
1.times{|bi|
|
||||
'abc'.split(/b/)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_block_pass
|
||||
ae %q{
|
||||
def getproc &b
|
||||
b
|
||||
end
|
||||
def m
|
||||
yield
|
||||
end
|
||||
m(&getproc{
|
||||
"test"
|
||||
})
|
||||
}
|
||||
ae %q{
|
||||
def getproc &b
|
||||
b
|
||||
end
|
||||
def m a
|
||||
yield a
|
||||
end
|
||||
m(123, &getproc{|block_a|
|
||||
block_a
|
||||
})
|
||||
}
|
||||
ae %q{
|
||||
def getproc &b
|
||||
b
|
||||
end
|
||||
def m *a
|
||||
yield a
|
||||
end
|
||||
m(123, 456, &getproc{|block_a|
|
||||
block_a
|
||||
})
|
||||
}
|
||||
ae %q{
|
||||
def getproc &b
|
||||
b
|
||||
end
|
||||
[1,2,3].map(&getproc{|block_e| block_e*block_e})
|
||||
}
|
||||
ae %q{
|
||||
def m a, b, &c
|
||||
c.call(a, b)
|
||||
end
|
||||
m(10, 20){|x, y|
|
||||
[x+y, x*y]
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
def m &b
|
||||
b
|
||||
end
|
||||
m(&nil)
|
||||
}
|
||||
ae %q{
|
||||
def m a, &b
|
||||
[a, b]
|
||||
end
|
||||
m(1, &nil)
|
||||
}
|
||||
ae %q{
|
||||
def m a
|
||||
[a, block_given?]
|
||||
end
|
||||
m(1, &nil)
|
||||
}
|
||||
end
|
||||
|
||||
def test_method_missing
|
||||
ae %q{
|
||||
class C
|
||||
def method_missing id
|
||||
id
|
||||
end
|
||||
end
|
||||
C.new.hoge
|
||||
} do
|
||||
remove_const :C
|
||||
end
|
||||
|
||||
ae %q{
|
||||
class C
|
||||
def method_missing *args, &b
|
||||
b.call(args)
|
||||
end
|
||||
end
|
||||
C.new.foo(1){|args|
|
||||
args
|
||||
}
|
||||
C.new.foo(1){|args|
|
||||
args
|
||||
} +
|
||||
C.new.foo(1, 2){|args|
|
||||
args
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_svar
|
||||
ae %q{
|
||||
'abc'.match(/a(b)c/)
|
||||
$1
|
||||
}
|
||||
end
|
||||
|
||||
def test_nested_method
|
||||
ae %q{
|
||||
class A
|
||||
def m
|
||||
def m2
|
||||
p :m2
|
||||
end
|
||||
m2()
|
||||
end
|
||||
end
|
||||
A.new.m
|
||||
}
|
||||
ae %q{
|
||||
class A
|
||||
def m
|
||||
def m2
|
||||
p :m2
|
||||
end
|
||||
m2()
|
||||
end
|
||||
end
|
||||
instance_eval('A.new.m')
|
||||
}
|
||||
end
|
||||
|
||||
def test_private_class_method
|
||||
ae %q{
|
||||
class C
|
||||
def self.m
|
||||
:ok
|
||||
end
|
||||
def self.test
|
||||
m
|
||||
end
|
||||
private_class_method :m
|
||||
end
|
||||
C.test
|
||||
}
|
||||
end
|
||||
|
||||
def test_alias_and_private
|
||||
ae %q{ # [yarv-dev:899]
|
||||
$ans = []
|
||||
class C
|
||||
def m
|
||||
$ans << "OK"
|
||||
end
|
||||
end
|
||||
C.new.m
|
||||
class C
|
||||
alias mm m
|
||||
private :mm
|
||||
end
|
||||
C.new.m
|
||||
begin
|
||||
C.new.mm
|
||||
rescue NoMethodError
|
||||
$ans << "OK!"
|
||||
end
|
||||
$ans
|
||||
}
|
||||
end
|
||||
|
||||
def test_break_from_defined_method
|
||||
ae %q{
|
||||
class C
|
||||
define_method(:foo){
|
||||
break :ok
|
||||
}
|
||||
end
|
||||
C.new.foo
|
||||
}
|
||||
end
|
||||
|
||||
def test_return_from_defined_method
|
||||
ae %q{
|
||||
class C
|
||||
define_method(:m){
|
||||
return :ok
|
||||
}
|
||||
end
|
||||
C.new.m
|
||||
}
|
||||
end
|
||||
end
|
||||
|
118
yarvtest/test_opts.rb
Normal file
118
yarvtest/test_opts.rb
Normal file
|
@ -0,0 +1,118 @@
|
|||
require 'yarvtest/yarvtest'
|
||||
|
||||
class TestOpt < YarvTestBase
|
||||
def test_plus
|
||||
ae %q{
|
||||
a, b = 1, 2
|
||||
a+b
|
||||
}
|
||||
ae %q{
|
||||
class Fixnum
|
||||
def +(*o)
|
||||
o
|
||||
end
|
||||
def -(*o)
|
||||
o
|
||||
end
|
||||
end
|
||||
[10+11, 100-101]
|
||||
}
|
||||
ae %q{
|
||||
class Float
|
||||
def +(o)
|
||||
self * o
|
||||
end
|
||||
end
|
||||
|
||||
a, b = 1, 2
|
||||
a+b
|
||||
}
|
||||
end
|
||||
|
||||
def test_opt_methdos
|
||||
klasses = [[Fixnum, 2, 3], [Float, 1.1, 2.2],
|
||||
[String, "abc", "def"], [Array, [1,2,3], [4, 5]],
|
||||
[Hash, {:a=>1, :b=>2}, {:x=>"foo", :y=>"bar"}]]
|
||||
|
||||
bin_methods = [:+, :-, :*, :/, :%, ]
|
||||
one_methods = [:length, :succ, ]
|
||||
ary = []
|
||||
|
||||
bin_methods.each{|m|
|
||||
klasses.each{|klass, obj, arg|
|
||||
str = %{
|
||||
ary = []
|
||||
if (#{obj.inspect}).respond_to? #{m.inspect}
|
||||
begin
|
||||
ary << (#{obj.inspect}).#{m.to_s}(#{arg.inspect})
|
||||
rescue Exception => e
|
||||
ary << :error
|
||||
end
|
||||
end
|
||||
|
||||
class #{klass}
|
||||
def #{m}(o)
|
||||
[#{m.inspect}, :bin, #{klass}].inspect
|
||||
end
|
||||
end
|
||||
ary << (#{obj.inspect}).#{m.to_s}(#{arg.inspect})
|
||||
ary
|
||||
}
|
||||
ae str
|
||||
}
|
||||
}
|
||||
one_methods.each{|m|
|
||||
klasses.each{|klass, obj|
|
||||
str = %{
|
||||
ary = []
|
||||
if (#{obj.inspect}).respond_to? #{m.inspect}
|
||||
ary << (#{obj.inspect}).#{m.to_s}()
|
||||
end
|
||||
|
||||
class #{klass}
|
||||
def #{m}()
|
||||
[#{m.inspect}, self, #{klass}].inspect
|
||||
end
|
||||
end
|
||||
ary << (#{obj.inspect}).#{m.to_s}()
|
||||
ary
|
||||
}
|
||||
ae str
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_opt_plus
|
||||
ae %q{
|
||||
temp = 2**30 - 5
|
||||
(1..5).map do
|
||||
temp += 1
|
||||
[temp, temp.class]
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
temp = -(2**30 - 5)
|
||||
(1..10).map do
|
||||
temp += 1
|
||||
[temp, temp.class]
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_eq
|
||||
ae %q{
|
||||
class Foo
|
||||
def ==(other)
|
||||
true
|
||||
end
|
||||
end
|
||||
foo = Foo.new
|
||||
[1.0 == foo,
|
||||
1 == foo,
|
||||
"abc" == foo,
|
||||
]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
293
yarvtest/test_proc.rb
Normal file
293
yarvtest/test_proc.rb
Normal file
|
@ -0,0 +1,293 @@
|
|||
require 'yarvtest/yarvtest'
|
||||
|
||||
class TestProc < YarvTestBase
|
||||
def test_simpleproc
|
||||
ae %q{
|
||||
def m(&b)
|
||||
b
|
||||
end
|
||||
m{1}.call
|
||||
}
|
||||
|
||||
ae %q{
|
||||
def m(&b)
|
||||
b
|
||||
end
|
||||
|
||||
m{
|
||||
a = 1
|
||||
a + 2
|
||||
}.call
|
||||
}
|
||||
end
|
||||
|
||||
def test_procarg
|
||||
ae %q{
|
||||
def m(&b)
|
||||
b
|
||||
end
|
||||
|
||||
m{|e_proctest| e_proctest}.call(1)
|
||||
}
|
||||
|
||||
ae %q{
|
||||
def m(&b)
|
||||
b
|
||||
end
|
||||
|
||||
m{|e_proctest1, e_proctest2|
|
||||
a = e_proctest1 * e_proctest2 * 2
|
||||
a * 3
|
||||
}.call(1, 2)
|
||||
}
|
||||
|
||||
ae %q{
|
||||
[
|
||||
Proc.new{|*args| args}.call(),
|
||||
Proc.new{|*args| args}.call(1),
|
||||
Proc.new{|*args| args}.call(1, 2),
|
||||
Proc.new{|*args| args}.call(1, 2, 3),
|
||||
]
|
||||
}
|
||||
ae %q{
|
||||
[
|
||||
Proc.new{|a, *b| [a, b]}.call(),
|
||||
Proc.new{|a, *b| [a, b]}.call(1),
|
||||
Proc.new{|a, *b| [a, b]}.call(1, 2),
|
||||
Proc.new{|a, *b| [a, b]}.call(1, 2, 3),
|
||||
]
|
||||
}
|
||||
end
|
||||
|
||||
def test_closure
|
||||
ae %q{
|
||||
def make_proc(&b)
|
||||
b
|
||||
end
|
||||
|
||||
def make_closure
|
||||
a = 0
|
||||
make_proc{
|
||||
a+=1
|
||||
}
|
||||
end
|
||||
|
||||
cl = make_closure
|
||||
cl.call + cl.call * cl.call
|
||||
}
|
||||
end
|
||||
|
||||
def test_nestproc2
|
||||
ae %q{
|
||||
def iter
|
||||
yield
|
||||
end
|
||||
|
||||
def getproc &b
|
||||
b
|
||||
end
|
||||
|
||||
iter{
|
||||
bvar = 3
|
||||
getproc{
|
||||
bvar2 = 4
|
||||
bvar * bvar2
|
||||
}
|
||||
}.call
|
||||
}
|
||||
|
||||
ae %q{
|
||||
def iter
|
||||
yield
|
||||
end
|
||||
|
||||
def getproc &b
|
||||
b
|
||||
end
|
||||
|
||||
loc1 = 0
|
||||
pr1 = iter{
|
||||
bl1 = 1
|
||||
getproc{
|
||||
loc1 += 1
|
||||
bl1 += 1
|
||||
loc1 + bl1
|
||||
}
|
||||
}
|
||||
|
||||
pr2 = iter{
|
||||
bl1 = 1
|
||||
getproc{
|
||||
loc1 += 1
|
||||
bl1 += 1
|
||||
loc1 + bl1
|
||||
}
|
||||
}
|
||||
|
||||
pr1.call; pr2.call
|
||||
pr1.call; pr2.call
|
||||
pr1.call; pr2.call
|
||||
(pr1.call + pr2.call) * loc1
|
||||
}
|
||||
end
|
||||
|
||||
def test_proc_with_cref
|
||||
ae %q{
|
||||
Const = :top
|
||||
class C
|
||||
Const = :C
|
||||
$pr = proc{
|
||||
(1..2).map{
|
||||
Const
|
||||
}
|
||||
}
|
||||
end
|
||||
$pr.call
|
||||
}
|
||||
ae %q{
|
||||
Const = :top
|
||||
class C
|
||||
Const = :C
|
||||
end
|
||||
pr = proc{
|
||||
Const
|
||||
}
|
||||
C.class_eval %q{
|
||||
pr.call
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_3nest
|
||||
ae %q{
|
||||
def getproc &b
|
||||
b
|
||||
end
|
||||
|
||||
def m
|
||||
yield
|
||||
end
|
||||
|
||||
m{
|
||||
i = 1
|
||||
m{
|
||||
j = 2
|
||||
m{
|
||||
k = 3
|
||||
getproc{
|
||||
[i, j, k]
|
||||
}
|
||||
}
|
||||
}
|
||||
}.call
|
||||
}
|
||||
end
|
||||
|
||||
def test_nestproc1
|
||||
ae %q{
|
||||
def proc &b
|
||||
b
|
||||
end
|
||||
|
||||
pr = []
|
||||
proc{|i_b|
|
||||
p3 = proc{|j_b|
|
||||
pr << proc{|k_b|
|
||||
[i_b, j_b, k_b]
|
||||
}
|
||||
}
|
||||
p3.call(1)
|
||||
p3.call(2)
|
||||
}.call(0)
|
||||
|
||||
pr[0].call(:last).concat pr[1].call(:last)
|
||||
}
|
||||
end
|
||||
|
||||
def test_proc_with_block
|
||||
ae %q{
|
||||
def proc(&pr)
|
||||
pr
|
||||
end
|
||||
|
||||
def m
|
||||
a = 1
|
||||
m2{
|
||||
a
|
||||
}
|
||||
end
|
||||
|
||||
def m2
|
||||
b = 2
|
||||
proc{
|
||||
[yield, b]
|
||||
}
|
||||
end
|
||||
|
||||
pr = m
|
||||
x = ['a', 1,2,3,4,5,6,7,8,9,0,
|
||||
1,2,3,4,5,6,7,8,9,0,
|
||||
1,2,3,4,5,6,7,8,9,0,
|
||||
1,2,3,4,5,6,7,8,9,0,
|
||||
1,2,3,4,5,6,7,8,9,0,]
|
||||
pr.call
|
||||
}
|
||||
ae %q{
|
||||
def proc(&pr)
|
||||
pr
|
||||
end
|
||||
|
||||
def m
|
||||
a = 1
|
||||
m2{
|
||||
a
|
||||
}
|
||||
end
|
||||
|
||||
def m2
|
||||
b = 2
|
||||
proc{
|
||||
[yield, b]
|
||||
}
|
||||
100000.times{|x|
|
||||
"#{x}"
|
||||
}
|
||||
yield
|
||||
end
|
||||
m
|
||||
}
|
||||
end
|
||||
|
||||
def test_method_to_proc
|
||||
ae %q{
|
||||
class C
|
||||
def foo
|
||||
:ok
|
||||
end
|
||||
end
|
||||
|
||||
def block
|
||||
C.method(:new).to_proc
|
||||
end
|
||||
b = block()
|
||||
b.call.foo
|
||||
}
|
||||
end
|
||||
|
||||
def test_safe
|
||||
ae %q{
|
||||
pr = proc{
|
||||
$SAFE
|
||||
}
|
||||
$SAFE = 1
|
||||
pr.call
|
||||
}
|
||||
ae %q{
|
||||
pr = proc{
|
||||
$SAFE += 1
|
||||
}
|
||||
[pr.call, $SAFE]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
594
yarvtest/test_syntax.rb
Normal file
594
yarvtest/test_syntax.rb
Normal file
|
@ -0,0 +1,594 @@
|
|||
require 'yarvtest/yarvtest'
|
||||
|
||||
# test of syntax
|
||||
class TestSYNTAX < YarvTestBase
|
||||
|
||||
def test_if_unless
|
||||
ae %q(if true then 1 ; end)
|
||||
ae %q(if false then 1 ; end)
|
||||
ae %q(if true then 1 ; else; 2; end)
|
||||
ae %q(if false then 1 ; else; 2; end)
|
||||
ae %q(if true then ; elsif true then ; 1 ; end)
|
||||
ae %q(if false then ; elsif true then ; 1 ; end)
|
||||
|
||||
ae %q(unless true then 1 ; end)
|
||||
ae %q(unless false then 1 ; end)
|
||||
ae %q(unless true then 1 ; else; 2; end)
|
||||
ae %q(unless false then 1 ; else; 2; end)
|
||||
|
||||
ae %q(1 if true)
|
||||
ae %q(1 if false)
|
||||
ae %q(1 if nil)
|
||||
|
||||
ae %q(1 unless true)
|
||||
ae %q(1 unless false)
|
||||
ae %q(1 unless nil)
|
||||
end
|
||||
|
||||
def test_while_until
|
||||
ae %q(
|
||||
i = 0
|
||||
while i < 10
|
||||
i+=1
|
||||
end)
|
||||
|
||||
ae %q(
|
||||
i = 0
|
||||
while i < 10
|
||||
i+=1
|
||||
end; i)
|
||||
|
||||
ae %q(
|
||||
i = 0
|
||||
until i > 10
|
||||
i+=1
|
||||
end)
|
||||
|
||||
ae %q(
|
||||
i = 0
|
||||
until i > 10
|
||||
i+=1
|
||||
end; i)
|
||||
#
|
||||
ae %q{
|
||||
i = 0
|
||||
begin
|
||||
i+=1
|
||||
end while false
|
||||
i
|
||||
}
|
||||
ae %q{
|
||||
i = 0
|
||||
begin
|
||||
i+=1
|
||||
end until true
|
||||
i
|
||||
}
|
||||
end
|
||||
|
||||
def test_and
|
||||
ae %q(1 && 2 && 3 && 4)
|
||||
ae %q(1 && nil && 3 && 4)
|
||||
ae %q(1 && 2 && 3 && nil)
|
||||
ae %q(1 && 2 && 3 && false)
|
||||
|
||||
ae %q(1 and 2 and 3 and 4)
|
||||
ae %q(1 and nil and 3 and 4)
|
||||
ae %q(1 and 2 and 3 and nil)
|
||||
ae %q(1 and 2 and 3 and false)
|
||||
ae %q(nil && true)
|
||||
ae %q(false && true)
|
||||
|
||||
end
|
||||
|
||||
def test_or
|
||||
ae %q(1 || 2 || 3 || 4)
|
||||
ae %q(1 || false || 3 || 4)
|
||||
ae %q(nil || 2 || 3 || 4)
|
||||
ae %q(false || 2 || 3 || 4)
|
||||
ae %q(nil || false || nil || false)
|
||||
|
||||
ae %q(1 or 2 or 3 or 4)
|
||||
ae %q(1 or false or 3 or 4)
|
||||
ae %q(nil or 2 or 3 or 4)
|
||||
ae %q(false or 2 or 3 or 4)
|
||||
ae %q(nil or false or nil or false)
|
||||
end
|
||||
|
||||
def test_case
|
||||
ae %q(
|
||||
case 1
|
||||
when 2
|
||||
:ng
|
||||
end)
|
||||
|
||||
ae %q(
|
||||
case 1
|
||||
when 10,20,30
|
||||
:ng1
|
||||
when 1,2,3
|
||||
:ok
|
||||
when 100,200,300
|
||||
:ng2
|
||||
else
|
||||
:elseng
|
||||
end)
|
||||
ae %q(
|
||||
case 123
|
||||
when 10,20,30
|
||||
:ng1
|
||||
when 1,2,3
|
||||
:ng2
|
||||
when 100,200,300
|
||||
:ng3
|
||||
else
|
||||
:elseok
|
||||
end
|
||||
)
|
||||
ae %q(
|
||||
case 'test'
|
||||
when /testx/
|
||||
:ng1
|
||||
when /test/
|
||||
:ok
|
||||
when /tetxx/
|
||||
:ng2
|
||||
else
|
||||
:ng_else
|
||||
end
|
||||
)
|
||||
ae %q(
|
||||
case Object.new
|
||||
when Object
|
||||
:ok
|
||||
end
|
||||
)
|
||||
ae %q(
|
||||
case Object
|
||||
when Object.new
|
||||
:ng
|
||||
else
|
||||
:ok
|
||||
end
|
||||
)
|
||||
ae %q{
|
||||
case 'test'
|
||||
when 'tes'
|
||||
:ng
|
||||
when 'te'
|
||||
:ng
|
||||
else
|
||||
:ok
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
case 'test'
|
||||
when 'tes'
|
||||
:ng
|
||||
when 'te'
|
||||
:ng
|
||||
when 'test'
|
||||
:ok
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
case 'test'
|
||||
when 'tes'
|
||||
:ng
|
||||
when /te/
|
||||
:ng
|
||||
else
|
||||
:ok
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
case 'test'
|
||||
when 'tes'
|
||||
:ng
|
||||
when /test/
|
||||
:ok
|
||||
else
|
||||
:ng
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
def test(arg)
|
||||
case 1
|
||||
when 2
|
||||
3
|
||||
end
|
||||
return arg
|
||||
end
|
||||
|
||||
test(100)
|
||||
}
|
||||
end
|
||||
|
||||
def test_case_splat
|
||||
ae %q{
|
||||
ary = [1, 2]
|
||||
case 1
|
||||
when *ary
|
||||
:ok
|
||||
else
|
||||
:ng
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
ary = [1, 2]
|
||||
case 3
|
||||
when *ary
|
||||
:ng
|
||||
else
|
||||
:ok
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
ary = [1, 2]
|
||||
case 1
|
||||
when :x, *ary
|
||||
:ok
|
||||
when :z
|
||||
:ng1
|
||||
else
|
||||
:ng2
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
ary = [1, 2]
|
||||
case 3
|
||||
when :x, *ary
|
||||
:ng1
|
||||
when :z
|
||||
:ng2
|
||||
else
|
||||
:ok
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_when
|
||||
ae %q(
|
||||
case
|
||||
when 1==2, 2==3
|
||||
:ng1
|
||||
when false, 4==5
|
||||
:ok
|
||||
when false
|
||||
:ng2
|
||||
else
|
||||
:elseng
|
||||
end
|
||||
)
|
||||
|
||||
ae %q(
|
||||
case
|
||||
when nil, nil
|
||||
:ng1
|
||||
when 1,2,3
|
||||
:ok
|
||||
when false, false
|
||||
:ng2
|
||||
else
|
||||
:elseng
|
||||
end
|
||||
)
|
||||
|
||||
ae %q(
|
||||
case
|
||||
when nil
|
||||
:ng1
|
||||
when false
|
||||
:ng2
|
||||
else
|
||||
:elseok
|
||||
end)
|
||||
|
||||
ae %q{
|
||||
case
|
||||
when 1
|
||||
end
|
||||
}
|
||||
|
||||
ae %q{
|
||||
r = nil
|
||||
ary = []
|
||||
case
|
||||
when false
|
||||
r = :ng1
|
||||
when false, false
|
||||
r = :ng2
|
||||
when *ary
|
||||
r = :ng3
|
||||
when false, *ary
|
||||
r = :ng4
|
||||
when true, *ary
|
||||
r = :ok
|
||||
end
|
||||
r
|
||||
}
|
||||
end
|
||||
|
||||
def test_when_splat
|
||||
ae %q{
|
||||
ary = []
|
||||
case
|
||||
when false, *ary
|
||||
:ng
|
||||
else
|
||||
:ok
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
ary = [false, nil]
|
||||
case
|
||||
when *ary
|
||||
:ng
|
||||
else
|
||||
:ok
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
ary = [false, nil]
|
||||
case
|
||||
when *ary
|
||||
:ng
|
||||
when true
|
||||
:ok
|
||||
else
|
||||
:ng2
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
ary = [false, nil]
|
||||
case
|
||||
when *ary
|
||||
:ok
|
||||
else
|
||||
:ng
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
ary = [false, true]
|
||||
case
|
||||
when *ary
|
||||
:ok
|
||||
else
|
||||
:ng
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
ary = [false, true]
|
||||
case
|
||||
when false, false
|
||||
when false, *ary
|
||||
:ok
|
||||
else
|
||||
:ng
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_flipflop
|
||||
ae %q{
|
||||
sum = 0
|
||||
30.times{|ib|
|
||||
if ib % 10 == 0 .. true
|
||||
sum += ib
|
||||
end
|
||||
}
|
||||
sum
|
||||
}
|
||||
ae %q{
|
||||
sum = 0
|
||||
30.times{|ib|
|
||||
if ib % 10 == 0 ... true
|
||||
sum += ib
|
||||
end
|
||||
}
|
||||
sum
|
||||
}
|
||||
ae %q{
|
||||
t = nil
|
||||
unless ''.respond_to? :lines
|
||||
class String
|
||||
def lines
|
||||
self
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
"this must not print
|
||||
Type: NUM
|
||||
123
|
||||
456
|
||||
Type: ARP
|
||||
aaa
|
||||
bbb
|
||||
\f
|
||||
this must not print
|
||||
hoge
|
||||
Type: ARP
|
||||
aaa
|
||||
bbb
|
||||
".lines.each{|l|
|
||||
if (t = l[/^Type: (.*)/, 1])..(/^\f/ =~ l)
|
||||
p [t, l]
|
||||
end
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_defined_vars
|
||||
ae %q{
|
||||
defined?(nil) + defined?(self) +
|
||||
defined?(true) + defined?(false)
|
||||
}
|
||||
#ae %q{
|
||||
# a = 1
|
||||
# defined?(a) # yarv returns "in block" in eval context
|
||||
#}
|
||||
ae %q{
|
||||
defined?(@a)
|
||||
}
|
||||
ae %q{
|
||||
@a = 1
|
||||
defined?(@a)
|
||||
}
|
||||
ae %q{
|
||||
defined?(@@a)
|
||||
}
|
||||
ae %q{
|
||||
@@a = 1
|
||||
defined?(@@a)
|
||||
}
|
||||
ae %q{
|
||||
defined?($a)
|
||||
}
|
||||
ae %q{
|
||||
$a = 1
|
||||
defined?($a)
|
||||
}
|
||||
ae %q{
|
||||
defined?(C_definedtest)
|
||||
}
|
||||
ae %q{
|
||||
C_definedtest = 1
|
||||
defined?(C_definedtest)
|
||||
} do
|
||||
remove_const :C_definedtest
|
||||
end
|
||||
|
||||
ae %q{
|
||||
defined?(::C_definedtest)
|
||||
}
|
||||
ae %q{
|
||||
C_definedtest = 1
|
||||
defined?(::C_definedtest)
|
||||
} do
|
||||
remove_const :C_definedtest
|
||||
end
|
||||
|
||||
ae %q{
|
||||
defined?(C_definedtestA::C_definedtestB::C_definedtestC)
|
||||
}
|
||||
ae %q{
|
||||
class C_definedtestA
|
||||
class C_definedtestB
|
||||
C_definedtestC = 1
|
||||
end
|
||||
end
|
||||
defined?(C_definedtestA::C_definedtestB::C_definedtestC)
|
||||
} do
|
||||
remove_const :C_definedtestA
|
||||
end
|
||||
end
|
||||
|
||||
def test_defined_method
|
||||
ae %q{
|
||||
defined?(m)
|
||||
}
|
||||
ae %q{
|
||||
def m
|
||||
end
|
||||
defined?(m)
|
||||
}
|
||||
|
||||
ae %q{
|
||||
defined?(a.class)
|
||||
}
|
||||
ae %q{
|
||||
a = 1
|
||||
defined?(a.class)
|
||||
}
|
||||
ae %q{
|
||||
class C
|
||||
def test
|
||||
[defined?(m1()), defined?(self.m1), defined?(C.new.m1),
|
||||
defined?(m2()), defined?(self.m2), defined?(C.new.m2),
|
||||
defined?(m3()), defined?(self.m3), defined?(C.new.m3)]
|
||||
end
|
||||
def m1
|
||||
end
|
||||
private
|
||||
def m2
|
||||
end
|
||||
protected
|
||||
def m3
|
||||
end
|
||||
end
|
||||
C.new.test + [defined?(C.new.m3)]
|
||||
}
|
||||
ae %q{
|
||||
$ans = [defined?($1), defined?($2), defined?($3), defined?($4)]
|
||||
/(a)(b)/ =~ 'ab'
|
||||
$ans + [defined?($1), defined?($2), defined?($3), defined?($4)]
|
||||
}
|
||||
end
|
||||
|
||||
def test_condition
|
||||
ae %q{
|
||||
|
||||
def make_perm ary, num
|
||||
if num == 1
|
||||
ary.map{|e| [e]}
|
||||
else
|
||||
base = make_perm(ary, num-1)
|
||||
res = []
|
||||
base.each{|b|
|
||||
ary.each{|e|
|
||||
res << [e] + b
|
||||
}
|
||||
}
|
||||
res
|
||||
end
|
||||
end
|
||||
|
||||
def each_test
|
||||
conds = make_perm(['fv', 'tv'], 3)
|
||||
bangs = make_perm(['', '!'], 3)
|
||||
exprs = make_perm(['and', 'or'], 3)
|
||||
['if', 'unless'].each{|syn|
|
||||
conds.each{|cs|
|
||||
bangs.each{|bs|
|
||||
exprs.each{|es|
|
||||
yield(syn, cs, bs, es)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
fv = false
|
||||
tv = true
|
||||
|
||||
$ans = []
|
||||
each_test{|syn, conds, bangs, exprs|
|
||||
c1, c2, c3 = conds
|
||||
bang1, bang2, bang3 = bangs
|
||||
e1, e2 = exprs
|
||||
eval %Q{
|
||||
#{syn} #{bang1}#{c1} #{e1} #{bang2}#{c2} #{e2} #{bang3}#{c3}
|
||||
$ans << :then
|
||||
else
|
||||
$ans << :false
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
each_test{|syn, conds, bangs, exprs|
|
||||
c1, c2, c3 = conds
|
||||
bang1, bang2, bang3 = bangs
|
||||
e1, e2 = exprs
|
||||
eval %Q{
|
||||
#{syn} #{bang1}#{c1} #{e1} #{bang2}#{c2} #{e2} #{bang3}#{c3}
|
||||
$ans << :then
|
||||
end
|
||||
$ans << :sep
|
||||
}
|
||||
}
|
||||
$ans
|
||||
}
|
||||
end
|
||||
end
|
||||
|
8
yarvtest/test_test.rb
Normal file
8
yarvtest/test_test.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
require 'yarvtest/yarvtest'
|
||||
|
||||
# test of syntax
|
||||
class TestTest < YarvTestBase
|
||||
def test_1
|
||||
ae '100'
|
||||
end
|
||||
end
|
209
yarvtest/test_thread.rb
Normal file
209
yarvtest/test_thread.rb
Normal file
|
@ -0,0 +1,209 @@
|
|||
|
||||
require 'yarvtest/yarvtest'
|
||||
|
||||
class TestThread < YarvTestBase
|
||||
def test_create
|
||||
ae %q{
|
||||
Thread.new{
|
||||
}.join
|
||||
:ok
|
||||
}
|
||||
ae %q{
|
||||
Thread.new{
|
||||
:ok
|
||||
}.value
|
||||
}
|
||||
end
|
||||
|
||||
def test_create_many_threads1
|
||||
ae %q{
|
||||
v = 0
|
||||
(1..200).map{|i|
|
||||
Thread.new{
|
||||
i
|
||||
}
|
||||
}.each{|t|
|
||||
v += t.value
|
||||
}
|
||||
v
|
||||
}
|
||||
end
|
||||
|
||||
def test_create_many_threads2
|
||||
ae %q{
|
||||
5000.times{|e|
|
||||
(1..2).map{
|
||||
Thread.new{
|
||||
}
|
||||
}.each{|e|
|
||||
e.join
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_create_many_threads3
|
||||
ae %q{
|
||||
5000.times{
|
||||
t = Thread.new{}
|
||||
while t.alive?
|
||||
Thread.pass
|
||||
end
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_create_many_threads4
|
||||
ae %q{
|
||||
100.times{
|
||||
Thread.new{loop{Thread.pass}}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_raise
|
||||
ae %q{
|
||||
t = Thread.new{
|
||||
sleep
|
||||
}
|
||||
sleep 0.1
|
||||
t.raise
|
||||
begin
|
||||
t.join
|
||||
:ng
|
||||
rescue
|
||||
:ok
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
t = Thread.new{
|
||||
loop{}
|
||||
}
|
||||
Thread.pass
|
||||
t.raise
|
||||
begin
|
||||
t.join
|
||||
:ng
|
||||
rescue
|
||||
:ok
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
t = Thread.new{
|
||||
}
|
||||
Thread.pass
|
||||
t.join
|
||||
t.raise # raise to exited thread
|
||||
begin
|
||||
t.join
|
||||
:ok
|
||||
rescue
|
||||
:ng
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_status
|
||||
ae %q{
|
||||
t = Thread.new{
|
||||
loop{}
|
||||
}
|
||||
st = t.status
|
||||
t.kill
|
||||
st
|
||||
}
|
||||
ae %q{
|
||||
t = Thread.new{
|
||||
sleep
|
||||
}
|
||||
sleep 0.1
|
||||
st = t.status
|
||||
t.kill
|
||||
st
|
||||
}
|
||||
ae %q{
|
||||
t = Thread.new{
|
||||
}
|
||||
t.kill
|
||||
sleep 0.1
|
||||
t.status
|
||||
}
|
||||
end
|
||||
|
||||
def test_tlv
|
||||
ae %q{
|
||||
Thread.current[:a] = 1
|
||||
Thread.new{
|
||||
Thread.current[:a] = 10
|
||||
Thread.pass
|
||||
Thread.current[:a]
|
||||
}.value + Thread.current[:a]
|
||||
}
|
||||
end
|
||||
|
||||
def test_thread_group
|
||||
ae %q{
|
||||
ptg = Thread.current.group
|
||||
Thread.new{
|
||||
ctg = Thread.current.group
|
||||
[ctg.class, ctg == ptg]
|
||||
}.value
|
||||
}
|
||||
ae %q{
|
||||
thg = ThreadGroup.new
|
||||
|
||||
t = Thread.new{
|
||||
thg.add Thread.current
|
||||
sleep
|
||||
}
|
||||
sleep 0.1
|
||||
[thg.list.size, ThreadGroup::Default.list.size]
|
||||
}
|
||||
end
|
||||
|
||||
def test_thread_local_svar
|
||||
ae %q{
|
||||
/a/ =~ 'a'
|
||||
$a = $~
|
||||
Thread.new{
|
||||
$b = $~
|
||||
/a/ =~ 'a'
|
||||
$c = $~
|
||||
}
|
||||
$d = $~
|
||||
[$a == $d, $b, $c != $d]
|
||||
}
|
||||
end
|
||||
|
||||
def test_join
|
||||
ae %q{
|
||||
Thread.new{
|
||||
:ok
|
||||
}.join.value
|
||||
}
|
||||
ae %q{
|
||||
begin
|
||||
Thread.new{
|
||||
raise "ok"
|
||||
}.join
|
||||
rescue => e
|
||||
e
|
||||
end
|
||||
}
|
||||
ae %q{
|
||||
ans = nil
|
||||
t = Thread.new{
|
||||
begin
|
||||
sleep 0.5
|
||||
ensure
|
||||
ans = :ok
|
||||
end
|
||||
}
|
||||
Thread.pass
|
||||
t.kill
|
||||
t.join
|
||||
ans
|
||||
}
|
||||
end
|
||||
end
|
||||
|
207
yarvtest/test_yield.rb
Normal file
207
yarvtest/test_yield.rb
Normal file
|
@ -0,0 +1,207 @@
|
|||
require 'yarvtest/yarvtest'
|
||||
class TestYield < YarvTestBase
|
||||
def test_simple
|
||||
ae %q{
|
||||
def iter
|
||||
yield
|
||||
end
|
||||
iter{
|
||||
1
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def test_hash_each
|
||||
ae %q{
|
||||
h = {:a => 1}
|
||||
a = []
|
||||
h.each{|k, v|
|
||||
a << [k, v]
|
||||
}
|
||||
h.each{|kv|
|
||||
a << kv
|
||||
}
|
||||
a
|
||||
}
|
||||
end
|
||||
|
||||
def test_ary_each
|
||||
ae %q{
|
||||
ans = []
|
||||
ary = [1,2,3]
|
||||
ary.each{|a, b, c, d|
|
||||
ans << [a, b, c, d]
|
||||
}
|
||||
ary.each{|a, b, c|
|
||||
ans << [a, b, c]
|
||||
}
|
||||
ary.each{|a, b|
|
||||
ans << [a, b]
|
||||
}
|
||||
ary.each{|a|
|
||||
ans << [a]
|
||||
}
|
||||
ans
|
||||
}
|
||||
end
|
||||
|
||||
def test_iter
|
||||
ae %q{
|
||||
def iter *args
|
||||
yield *args
|
||||
end
|
||||
|
||||
ans = []
|
||||
ary = [1,2,3]
|
||||
ary.each{|a, b, c, d|
|
||||
ans << [a, b, c, d]
|
||||
}
|
||||
ary.each{|a, b, c|
|
||||
ans << [a, b, c]
|
||||
}
|
||||
ary.each{|a, b|
|
||||
ans << [a, b]
|
||||
}
|
||||
ary.each{|a|
|
||||
ans << [a]
|
||||
}
|
||||
ans
|
||||
}
|
||||
end
|
||||
|
||||
def test_iter2
|
||||
ae %q{
|
||||
def iter args
|
||||
yield *args
|
||||
end
|
||||
ans = []
|
||||
iter([]){|a, b|
|
||||
ans << [a, b]
|
||||
}
|
||||
iter([1]){|a, b|
|
||||
ans << [a, b]
|
||||
}
|
||||
iter([1, 2]){|a, b|
|
||||
ans << [a, b]
|
||||
}
|
||||
iter([1, 2, 3]){|a, b|
|
||||
ans << [a, b]
|
||||
}
|
||||
ans
|
||||
}
|
||||
ae %q{
|
||||
def iter args
|
||||
yield *args
|
||||
end
|
||||
ans = []
|
||||
|
||||
iter([]){|a|
|
||||
ans << a
|
||||
}
|
||||
iter([1]){|a|
|
||||
ans << a
|
||||
}
|
||||
iter([1, 2]){|a|
|
||||
ans << a
|
||||
}
|
||||
iter([1, 2, 3]){|a|
|
||||
ans << a
|
||||
}
|
||||
ans
|
||||
}
|
||||
end
|
||||
|
||||
def test_1_ary_and_n_params
|
||||
ae %q{
|
||||
def iter args
|
||||
yield args
|
||||
end
|
||||
ans = []
|
||||
iter([]){|a, b|
|
||||
ans << [a, b]
|
||||
}
|
||||
iter([1]){|a, b|
|
||||
ans << [a, b]
|
||||
}
|
||||
iter([1, 2]){|a, b|
|
||||
ans << [a, b]
|
||||
}
|
||||
iter([1, 2, 3]){|a, b|
|
||||
ans << [a, b]
|
||||
}
|
||||
ans
|
||||
}
|
||||
end
|
||||
|
||||
def test_1_ary_and_1_params
|
||||
ae %q{
|
||||
def iter args
|
||||
yield args
|
||||
end
|
||||
ans = []
|
||||
iter([]){|a|
|
||||
ans << a
|
||||
}
|
||||
iter([1]){|a|
|
||||
ans << a
|
||||
}
|
||||
iter([1, 2]){|a|
|
||||
ans << a
|
||||
}
|
||||
iter([1, 2, 3]){|a|
|
||||
ans << a
|
||||
}
|
||||
ans
|
||||
}
|
||||
end
|
||||
|
||||
def test_argscat
|
||||
ae %q{
|
||||
def iter
|
||||
yield 1, *[2, 3]
|
||||
end
|
||||
|
||||
iter{|a, b, c|
|
||||
[a, b, c]
|
||||
}
|
||||
}
|
||||
ae %q{
|
||||
def iter
|
||||
yield 1, *[]
|
||||
end
|
||||
|
||||
iter{|a, b, c|
|
||||
[a, b, c]
|
||||
}
|
||||
}
|
||||
if false
|
||||
ae %q{
|
||||
def iter
|
||||
yield 1, *2
|
||||
end
|
||||
|
||||
iter{|a, b, c|
|
||||
[a, b, c]
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_massgin
|
||||
ae %q{
|
||||
ans = []
|
||||
[[1, [2, 3]], [4, [5, 6]]].each{|a, (b, c)|
|
||||
ans << [a, b, c]
|
||||
}
|
||||
ans
|
||||
}
|
||||
ae %q{
|
||||
ans = []
|
||||
[[1, [2, 3]], [4, [5, 6]]].map{|a, (b, c)|
|
||||
ans << [a, b, c]
|
||||
} + ans
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
136
yarvtest/yarvtest.rb
Normal file
136
yarvtest/yarvtest.rb
Normal file
|
@ -0,0 +1,136 @@
|
|||
require 'test/unit'
|
||||
|
||||
if defined? YARV_PATCHED
|
||||
require 'yarvutil'
|
||||
|
||||
class YarvTestBase < Test::Unit::TestCase
|
||||
|
||||
def remove_const sym
|
||||
Object.module_eval{
|
||||
remove_const sym
|
||||
}
|
||||
end
|
||||
|
||||
def remove_method sym
|
||||
Object.module_eval{
|
||||
undef sym
|
||||
}
|
||||
end
|
||||
|
||||
def ae str
|
||||
# puts str
|
||||
# puts YARVUtil.parse(str, $0, 0).disasm
|
||||
|
||||
ruby = YARVUtil.eval_in_wrap(str)
|
||||
yield if block_given?
|
||||
|
||||
yarv = YARVUtil.eval(str)
|
||||
yield if block_given?
|
||||
|
||||
assert_equal(ruby, yarv)
|
||||
end
|
||||
|
||||
def test_
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
require 'rbconfig'
|
||||
class YarvTestBase < Test::Unit::TestCase
|
||||
def initialize *args
|
||||
super
|
||||
|
||||
if /mswin32/ !~ RUBY_PLATFORM
|
||||
@yarv = './miniruby'
|
||||
else
|
||||
@yarv = 'miniruby'
|
||||
end
|
||||
@ruby = Config::CONFIG['ruby_install_name']
|
||||
end
|
||||
|
||||
def remove_const sym
|
||||
Object.module_eval{
|
||||
remove_const sym
|
||||
}
|
||||
end
|
||||
|
||||
def remove_method sym
|
||||
Object.module_eval{
|
||||
undef sym
|
||||
}
|
||||
end
|
||||
|
||||
require 'tempfile'
|
||||
def exec exec_file, program
|
||||
dir = []
|
||||
dir << ENV['RAMDISK'] if ENV['RAMDISK']
|
||||
tmpf = Tempfile.new("yarvtest_#{Process.pid}_#{Time.now.to_i}", *dir)
|
||||
tmpf.write program
|
||||
tmpf.close
|
||||
result = `#{exec_file} #{tmpf.path}`
|
||||
tmpf.open
|
||||
tmpf.close(true)
|
||||
result
|
||||
end
|
||||
|
||||
def dump_and_exec exec_file, str
|
||||
asmstr = <<-EOASMSTR
|
||||
iseq = YARVCore::InstructionSequence.compile(<<-'EOS__')
|
||||
#{str}
|
||||
EOS__
|
||||
p YARVCore::InstructionSequence.load(iseq.to_a).eval
|
||||
EOASMSTR
|
||||
|
||||
exec(exec_file, asmstr)
|
||||
end
|
||||
|
||||
def exec_ exec_file, program
|
||||
exec_file.tr!('\\', '/')
|
||||
r = ''
|
||||
IO.popen("#{exec_file}", 'r+'){|io|
|
||||
#
|
||||
io.write program
|
||||
io.close_write
|
||||
begin
|
||||
while line = io.gets
|
||||
r << line
|
||||
# p line
|
||||
end
|
||||
rescue => e
|
||||
# p e
|
||||
end
|
||||
}
|
||||
r
|
||||
end
|
||||
|
||||
def ae str
|
||||
evalstr = %{
|
||||
p eval(%q{
|
||||
#{str}
|
||||
})
|
||||
}
|
||||
|
||||
ruby = exec(@ruby, evalstr)
|
||||
yarv = exec(@yarv, evalstr)
|
||||
|
||||
if $DEBUG #|| true
|
||||
puts "yarv (#@yarv): #{yarv}"
|
||||
puts "ruby (#@ruby): #{ruby}"
|
||||
end
|
||||
|
||||
assert_equal(ruby.gsub(/\r/, ''), yarv.gsub(/\r/, ''))
|
||||
|
||||
# store/load test
|
||||
if false # || true
|
||||
yarvasm = dump_and_exec(@yarv, str)
|
||||
assert_equal(ruby.gsub(/\r/, ''), yarvasm.gsub(/\r/, ''))
|
||||
end
|
||||
end
|
||||
|
||||
def test_
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue