Rb_scan_args() for keyword arguments

Issue #227 has been updated by Akinori MUSHA.

キーワードに対応した値を取り出す部分はまだ入っていないです。
私の案とまつもとさんの案があって、どうしようかというところで止まっています。

本当に今Rubyに割ける時間がないのでポインタなしのコメントだけですみませんが、一応。


Feature #227: rb_scan_args() for keyword arguments

Author: Nobuyoshi N.
Status: Closed
Priority: Low
Assignee: Yukihiro M.
Category:
Target version: 1.9.x

=begin
なかだです。

rb_scan_args()でキーワード引数に対応するパッチを発掘しました。

rb_scan_args(argc, argv, “11:foo”, &mandatory, &optional, &foo)
とか
rb_scan_args(argc, argv, “11::”, &mandatory, &optional,
rb_intern(“foo”), &foo, (ID)0)
とか書けるようになるはずだったと思います。

Index: class.c

— class.c (revision 17903)
+++ class.c (working copy)
@@ -871,4 +871,5 @@ rb_scan_args(int argc, const VALUE *argv
const char *p = fmt;
VALUE *var;

  • VALUE opt = 0;
    va_list vargs;

@@ -876,4 +877,13 @@ rb_scan_args(int argc, const VALUE *argv

  if (*p == '*') goto rest_arg;
  • if (strchr(fmt, ‘:’)) {

  • if (argc > 0 && TYPE(opt = argv[argc-1]) == T_HASH) {

  •  --argc;
    
  • }

  • else {

  •  opt = 0;
    
  • }

  • if (*p == ‘:’) goto keyword;

  • }

    if (ISDIGIT(*p)) {
    @@ -895,9 +905,6 @@ rb_scan_args(int argc, const VALUE argv
    for (; i<n; i++) {
    var = va_arg(vargs, VALUE
    );

  •  if (argc > i) {
    
  • if (var) *var = argv[i];
  •  }
    
  •  else {
    
  • if (var) *var = Qnil;
  •  if (var) {
    
  • *var = argc > i ? argv[i] : Qnil;
    }
    }
    @@ -905,5 +912,32 @@ rb_scan_args(int argc, const VALUE *argv
    }
  • if(p == '') {
  • keyword:
  • if (*p == ‘:’) {
  • if (p[1] == ‘:’) {
  •  ID name;
    
  •  while ((name = va_arg(vargs, ID)) != 0) {
    
  • var = va_arg(vargs, VALUE*);
  • if (var) {
  •    *var = opt ? rb_hash_lookup(opt, name) : Qnil;
    
  • }
  •  }
    
  • }
  • else {
  •  do {
    
  • const char *beg = ++p;
  • if (*p != ‘_’ && !ISALPHA(*p)) goto error;
  • while (*p == ‘_’ || ISALNUM(*p)) p++;
  • if (p && !strchr(":&", *p)) goto error;
  • var = va_arg(vargs, VALUE*);
  • if (var) {
  •    *var = opt ?
    
  •  rb_hash_lookup(opt, rb_intern2(beg, p - beg)) :
    
  •  Qnil;
    
  • }
  •  } while (*p == ':');
    
  • }
  • }
  • if (p == '') {
    rest_arg:
    var = va_arg(vargs, VALUE*);


— 僕の前にBugはない。
— 僕の後ろにBugはできる。
中田 伸悦
=end