[ruby-dev:30851] Re: block wrapper
From:
Tanaka Akira <akr@...>
Date:
2007-05-31 02:53:36 UTC
List:
ruby-dev #30851
In article <465E1040.7020009@atdot.net>,
SASADA Koichi <ko1@atdot.net> writes:
> 私は、この件が一体何がどうなればよいのかわかっていないのです
> が、make test が全部通ればOKということなんでしょうか(以前、そ
> う伺った気がします)。今の trunk で「ここはこうしろ」と指摘し
> ていただけると大変助かります。
このスレッドの [ruby-dev:29078] に出したものを拡充したスクリ
プトをこのメールにつけてますので試してください。fail がひと
つでもあれば wrapper になっていないということになります。
実際、[ruby-dev:30780] で出した例はそのスクリプトで見付けた
ものです。
make test は網羅性に関しては信用していません。
> あと、Proc#yield は新設するんですか? 聞く人によって言うこ
> とが違うので、ちょっとよくわからないんですよね。最終的な仕様を
> 誰か教えてください。sample/test.rb には Proc#yield は存在します。
もし、Proc#yield を Proc#call と異なるものとして新設するのな
ら、その違いは wrapper で扱う値においてどう表現されるのですか?
ARGS = [
nil,
"",
"v1",
"v1,",
"v1,v2",
"v1,v2,v3",
"*v1",
"v1,*v2",
"v1,v2,*v3",
"v1,v2,v3,*v4",
#"v1,*v2,v3",
#"*v1,v2",
#"*v1,v2,v3"
]
YIELDS = %W[
yield
b.yield
b.call
]
VALUES = [
nil,
0,
[],
[0],
[[]],
[[0]],
[[[]]],
[0,0],
[0,[]],
[[],0],
[[],[]]
]
WRAPBLOCKS = [
"{|*v|yield(*v)}",
]
begin
eval "1.class {|**v| yield(**v)}"
rescue SyntaxError
WRAPBLOCKS.delete "{|**v|yield(**v)}"
end
ANONFUNCS = [
["__send__(callee_name, *vs) {%s [%s] }", "{%s}"],
["__send__(callee_name, *vs, &lambda {%s [%s] })", "&l{%s}"],
["__send__(callee_name, *vs, &proc {%s [%s] })", "&p{%s}"]
]
unless lambda{}.respond_to? :yield
YIELDS.delete("b.yield")
WRAPBLOCKS.reject! {|b| /b.yield/ =~ b }
end
# def calleeNN(vv) YIELD(ARGS) end
# def callerNN(callee_name, *vs) __send__(callee_name, *vs) {|ARGS| ... } end
# def callerNN(callee_name, *vs) __send__(callee_name, *vs, &lambda {|ARGS| ... }) end
#
# def wrapperNN(callee_name, *vs) __send__(callee_name, *vs) WRAPBLOCK end
CALLEE = []
def define_callee
name = "callee00"
ARGS.each {|as|
next if !as
next if as == 'v1,'
vars = as.scan(/v\d/)
varsb = (vars+['&b']).join(',')
YIELDS.each {|y|
name.succ!
n = name.dup
eval "def #{n}(#{varsb}) #{y}(#{as}) end"
CALLEE << [n, [vars.length, "#{y}(#{as})"]]
}
}
end
define_callee
CALLER = []
def define_caller
name = "caller00"
ANONFUNCS.each {|call_template, block_mesg|
ARGS.each {|as|
vars = as ? as.scan(/v\d/) : []
as = as ? "|#{as}|" : ''
name.succ!
n = name.dup
eval "def #{n}(callee_name, *vs) #{call_template % [as, vars.join(',')]} end"
CALLER << [n, block_mesg % as]
}
}
end
define_caller
WRAPPER = []
def define_wrapper
name = "wrapper00"
WRAPBLOCKS.each {|w|
name.succ!
n = name.dup
w2 = w.sub(/\|.*\|/) { $& + "$wrapper_value = v;" }
eval "def #{n}(callee_name, *vs, &b) __send__(callee_name, *vs) #{w2} end"
WRAPPER << [n, w]
}
end
define_wrapper
def perm(vs, n)
if n == 0
yield []
else
perm(vs, n-1) {|vv|
vs.each {|v| yield vv + [v] }
}
end
end
$VERBOSE = nil
def check(callee_name, callee_desc, wrapper_name, wrapper_desc, caller_name, caller_desc, vs)
r1 = (__send__(caller_name, callee_name, *vs) rescue $!)
r2 = (__send__(caller_name, wrapper_name, callee_name, *vs) rescue $!)
wv = $wrapper_value
success = r1 == r2 || (r1.kind_of?(Exception) && r2.kind_of?(Exception) && r1.class == r2.class && r1.message == r2.message)
print(success ? "succ\t" : "fail\t")
vs2 = vs.dup
cd = callee_desc.gsub(/v\d/) { vs2.shift.inspect }.gsub(/ /, '')
wd = (wrapper_desc + '/' + wv.inspect).gsub(/ /, '')
r1 = r1.inspect.gsub(/ /, r1.kind_of?(Exception) ? '_' : '')
r2 = r2.inspect.gsub(/ /, r2.kind_of?(Exception) ? '_' : '')
print cd, "\t"
print wd, "\t"
print caller_desc, "\t"
print r1, "\t"
print r2, "\n"
success
end
count = {}
error = {}
WRAPPER.each {|wrapper_name, wrapper_desc|
count[wrapper_desc] = 0
error[wrapper_desc] = 0
CALLEE.each {|callee_name, (callee_arity, callee_desc)|
perm(VALUES, callee_arity) {|vs|
CALLER.each {|caller_name, caller_desc|
count[wrapper_desc] += 1
success = check(callee_name, callee_desc, wrapper_name, wrapper_desc, caller_name, caller_desc, vs)
error[wrapper_desc] += 1 if !success
}
}
}
puts
}
WRAPPER.each {|wrapper_name, wrapper_desc|
c = count[wrapper_desc]
e = error[wrapper_desc]
puts "#{wrapper_desc}:\t#{e}/#{c}\t#{e*100.0/c}%"
}
--
[田中 哲][たなか あきら][Tanaka Akira]