summaryrefslogtreecommitdiff
path: root/iseq.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-11-28 04:19:37 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-11-28 04:19:37 +0000
commit46e3b0fe7b1d39bd783d1bab539f5624e80d73d6 (patch)
tree35e2e4ad9d9d9965b6642e264779787213490b93 /iseq.c
parent4d3f3af83689790f21b344abbfbe6bbdd483813e (diff)
* iseq.c (simple_default_value): extracts simplest default
argument value. * iseq.c (rb_iseq_parameters): returns parameter list. * proc.c (get_proc_iseq, get_method_iseq): handles ifunc and bmethod. * proc.c (rb_proc_parameters, rb_method_parameters): added Proc#parameters and Method#parameters. [ruby-core:19759] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20384 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'iseq.c')
-rw-r--r--iseq.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/iseq.c b/iseq.c
index c4ccc3c24e..54ae01f8c2 100644
--- a/iseq.c
+++ b/iseq.c
@@ -1274,6 +1274,84 @@ rb_iseq_clone(VALUE iseqval, VALUE newcbase)
return newiseq;
}
+static VALUE
+simple_default_value(const VALUE *seq, const VALUE *eseq)
+{
+ VALUE val;
+
+ again:
+ switch (*seq++) {
+ case BIN(trace):
+ if (++seq >= eseq) return Qundef;
+ goto again;
+ case BIN(putnil):
+ val = Qnil;
+ goto got;
+ case BIN(putobject):
+ val = *seq++;
+ got:
+ switch (*seq++) {
+ case BIN(setlocal):
+ if ((seq+=1) != eseq) return Qundef;
+ break;
+ case BIN(setdynamic):
+ if ((seq+=2) != eseq) return Qundef;
+ break;
+ }
+ return val;
+ default:
+ return Qundef;
+ }
+}
+
+VALUE
+rb_iseq_parameters(const rb_iseq_t *iseq)
+{
+ int i, r, s;
+ VALUE a, args = rb_ary_new2(iseq->arg_size);
+ ID req, opt, rest, block;
+#define PARAM_TYPE(type) rb_ary_push(a = rb_ary_new2(2), ID2SYM(type))
+#define PARAM_ID(i) iseq->local_table[i]
+#define PARAM(i, type) ( \
+ PARAM_TYPE(type), \
+ rb_id2name(PARAM_ID(i)) ? \
+ rb_ary_push(a, ID2SYM(PARAM_ID(i))) : \
+ a)
+
+ CONST_ID(req, "req");
+ for (i = 0; i < iseq->argc; i++) {
+ rb_ary_push(args, PARAM(i, req));
+ }
+ r = iseq->arg_rest != -1 ? iseq->arg_rest :
+ iseq->arg_post_len > 0 ? iseq->arg_post_start :
+ iseq->arg_block != -1 ? iseq->arg_block :
+ iseq->arg_size;
+ CONST_ID(opt, "opt");
+ for (s = i; i < r; i++) {
+ PARAM_TYPE(opt);
+ if (rb_id2name(PARAM_ID(i))) {
+ VALUE defval = simple_default_value(iseq->iseq + iseq->arg_opt_table[i-s],
+ iseq->iseq + iseq->arg_opt_table[i-s+1]);
+ rb_ary_push(a, ID2SYM(PARAM_ID(i)));
+ if (defval != Qundef) rb_ary_push(a, defval);
+ }
+ rb_ary_push(args, a);
+ }
+ if (iseq->arg_rest != -1) {
+ CONST_ID(rest, "rest");
+ rb_ary_push(args, PARAM(iseq->arg_rest, rest));
+ }
+ r = iseq->arg_post_start + iseq->arg_post_len;
+ for (i = iseq->arg_post_start; i < r; i++) {
+ rb_ary_push(args, PARAM(i, req));
+ }
+ if (iseq->arg_block != -1) {
+ CONST_ID(block, "block");
+ rb_ary_push(args, PARAM(iseq->arg_block, block));
+ }
+ return args;
+}
+
/* ruby2cext */
VALUE