From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-2.9 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=unavailable version=3.3.2 X-Original-To: spew@80x24.org Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 1823F1FA55; Sun, 23 Nov 2014 05:55:38 +0000 (UTC) Date: Sun, 23 Nov 2014 05:55:37 +0000 From: Eric Wong To: spew@80x24.org Subject: [WIP] rb_iseq_load bugs Message-ID: <20141123055537.GA1002@dcvr.yhbt.net> References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: List-Id: diff --git a/compile.c b/compile.c index d159360..52d772c 100644 --- a/compile.c +++ b/compile.c @@ -6015,6 +6015,45 @@ iseq_build_load_iseq(rb_iseq_t *iseq, VALUE op) return iseqval; } +static VALUE +build_callinfo_from_hash(rb_iseq_t *iseq, VALUE op) +{ + ID mid = 0; + int orig_argc = 0; + VALUE block = 0; + unsigned int flag = 0; + rb_call_info_kw_arg_t *kw_arg = 0; + + VALUE tmp = rb_inspect(op); + fprintf(stderr, "omg: %s\n", RSTRING_PTR(tmp)); + rb_str_resize(tmp, 0); + if (NIL_P(op)) { + VALUE vmid = rb_hash_aref(op, ID2SYM(rb_intern("mid"))); + VALUE vflag = rb_hash_aref(op, ID2SYM(rb_intern("flag"))); + VALUE vorig_argc = rb_hash_aref(op, ID2SYM(rb_intern("orig_argc"))); + VALUE vblock = rb_hash_aref(op, ID2SYM(rb_intern("blockptr"))); + VALUE vkw_arg = rb_hash_aref(op, ID2SYM(rb_intern("kw_arg"))); + + if (!NIL_P(vmid)) mid = SYM2ID(vmid); + if (!NIL_P(vflag)) flag = NUM2UINT(vflag); + if (!NIL_P(vorig_argc)) orig_argc = FIX2INT(vorig_argc); + if (!NIL_P(vblock)) block = iseq_build_load_iseq(iseq, vblock); + + if (!NIL_P(vkw_arg)) { + int len = RARRAY_LENINT(vkw_arg); + int i; + size_t n = sizeof(rb_call_info_kw_arg_t) + sizeof(ID) * (len - 1); + + kw_arg = xmalloc(n); + kw_arg->keyword_len = len; + for (i = 0; i < len; i++) { + kw_arg->keywords[i] = SYM2ID(RARRAY_AREF(vkw_arg, i)); + } + } + } + + return (VALUE)new_callinfo(iseq, mid, orig_argc, block, flag, kw_arg); +} static int iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor, VALUE body, struct st_table *labels_table) @@ -6103,25 +6142,8 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor, } break; case TS_CALLINFO: - { - ID mid = 0; - int orig_argc = 0; - VALUE block = 0; - unsigned int flag = 0; - - if (!NIL_P(op)) { - VALUE vmid = rb_hash_aref(op, ID2SYM(rb_intern("mid"))); - VALUE vflag = rb_hash_aref(op, ID2SYM(rb_intern("flag"))); - VALUE vorig_argc = rb_hash_aref(op, ID2SYM(rb_intern("orig_argc"))); - VALUE vblock = rb_hash_aref(op, ID2SYM(rb_intern("blockptr"))); - - if (!NIL_P(vmid)) mid = SYM2ID(vmid); - if (!NIL_P(vflag)) flag = NUM2UINT(vflag); - if (!NIL_P(vorig_argc)) orig_argc = FIX2INT(vorig_argc); - if (!NIL_P(vblock)) block = iseq_build_load_iseq(iseq, vblock); - } - argv[j] = (VALUE)new_callinfo(iseq, mid, orig_argc, block, flag, NULL /* TODO: support keywords */); - } + argv[j] = build_callinfo_from_hash(iseq, op); + break; case TS_ID: argv[j] = rb_convert_type(op, T_SYMBOL, @@ -6328,7 +6350,9 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, keywords); } - (void)int_param(&iseq->param.keyword->rest_start, params, SYM(kwrest)); + if (iseq->param.keyword) { + (void)int_param(&iseq->param.keyword->rest_start, params, SYM(kwrest)); + } if (Qtrue == rb_hash_aref(params, SYM(ambiguous_param0))) { iseq->param.flags.ambiguous_param0 = TRUE; } diff --git a/iseq.c b/iseq.c index fe647cb..5f3e7e3 100644 --- a/iseq.c +++ b/iseq.c @@ -1809,10 +1809,23 @@ iseq_data_to_ary(rb_iseq_t *iseq) { rb_call_info_t *ci = (rb_call_info_t *)*seq; VALUE e = rb_hash_new(); + fprintf(stderr, "ci->kw_arg %p\n", ci->kw_arg); rb_hash_aset(e, ID2SYM(rb_intern("mid")), ci->mid ? ID2SYM(ci->mid) : Qnil); - rb_hash_aset(e, ID2SYM(rb_intern("flag")), ULONG2NUM(ci->flag)); + rb_hash_aset(e, ID2SYM(rb_intern("flag")), UINT2NUM(ci->flag)); rb_hash_aset(e, ID2SYM(rb_intern("orig_argc")), INT2FIX(ci->orig_argc)); rb_hash_aset(e, ID2SYM(rb_intern("blockptr")), ci->blockiseq ? iseq_data_to_ary(ci->blockiseq) : Qnil); + + if (ci->kw_arg) { + int i; + VALUE kw = rb_ary_new2((long)ci->kw_arg->keyword_len); + + for (i = 0; i < ci->kw_arg->keyword_len; i++) { + rb_ary_push(kw, ID2SYM(ci->kw_arg->keywords[i])); + fprintf(stderr, "kw:arg %s\n", + RSTRING_PTR(rb_id2str(ci->kw_arg->keywords[i]))); + } + rb_hash_aset(e, ID2SYM(rb_intern("kw_arg")), kw); + } rb_ary_push(ary, e); } break; diff --git a/test/-ext-/iseq_load/test_iseq_load.rb b/test/-ext-/iseq_load/test_iseq_load.rb index ca0a940..028f5cc 100644 --- a/test/-ext-/iseq_load/test_iseq_load.rb +++ b/test/-ext-/iseq_load/test_iseq_load.rb @@ -64,6 +64,18 @@ end orig = iseq.to_a.freeze loaded = ISeq.iseq_load(orig.dup) assert_equal orig, loaded.to_a + + f = File.expand_path(__FILE__) + 3.times { f = File.dirname(f) } + f = File.join(f, 'ruby', 'test_keyword.rb') + iseq = ISeq.compile_file(f) + orig = iseq.to_a.freeze + require 'pp' + PP.pp orig, File.open("/tmp/a.rb", "w") + loaded = ISeq.iseq_load(orig.dup) + PP.pp loaded.to_a, File.open("/tmp/b.rb", "w") + assert_equal orig, loaded.to_a + if $DEBUG require 'pp' PP.pp orig, $stderr