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]