summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog36
-rw-r--r--enum.c144
-rw-r--r--enumerator.c44
-rw-r--r--env.h9
-rw-r--r--error.c2
-rw-r--r--eval.c898
-rw-r--r--ext/dbm/dbm.c24
-rw-r--r--ext/gdbm/gdbm.c11
-rw-r--r--ext/iconv/iconv.c2
-rw-r--r--ext/openssl/ossl_asn1.c2
-rw-r--r--ext/openssl/ossl_config.c2
-rw-r--r--ext/openssl/ossl_pkcs7.c4
-rw-r--r--ext/openssl/ossl_ssl.c2
-rw-r--r--ext/openssl/ossl_x509name.c2
-rw-r--r--ext/sdbm/init.c11
-rw-r--r--ext/socket/socket.c2
-rw-r--r--ext/syck/rubyext.c6
-rw-r--r--ext/win32ole/win32ole.c2
-rw-r--r--io.c2
-rw-r--r--lib/optparse.rb4
-rw-r--r--node.h2
-rw-r--r--numeric.c3
-rw-r--r--parse.y2
-rw-r--r--ruby.h1
-rw-r--r--struct.c8
-rw-r--r--test/ruby/envutil.rb9
-rw-r--r--test/webrick/test_filehandler.rb6
27 files changed, 653 insertions, 587 deletions
diff --git a/ChangeLog b/ChangeLog
index 66d1310..72e29de 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Fri Feb 3 17:57:02 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c: unify ruby_class (for method definition) and ruby_cbase
+ (for constant reference).
+
Fri Feb 3 15:02:10 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
* ext/syck/syck.c (syck_move_tokens): should reset p->cursor or etc
@@ -15,6 +20,17 @@ Thu Feb 2 17:13:01 2006 NAKAMURA Usaku <usa@ruby-lang.org>
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser#get_tk): added
support of :'string' style Symbol.
+Thu Feb 2 16:01:24 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_call0): use TMP_ALLOC() instead of allocating
+ a temporary array object.
+
+ * eval.c (eval): need not to protect $SAFE value.
+ [ruby-core:07177]
+
+ * error.c (Init_Exception): change NameError to direct subclass of
+ Exception so that default rescue do not handle it silently.
+
Thu Feb 2 14:45:53 2006 Ville Mattila <ville.mattila@stonesoft.com>
* configure.in: The isinf is not regognized by autoconf
@@ -29,6 +45,11 @@ Wed Feb 1 22:01:47 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
* ruby.c (set_arg0): if use setenv(3), environ space cannot be used
for altering argv[0].
+Tue Jan 31 14:46:28 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * struct.c (rb_struct_select): update RDoc description.
+ [ruby-core:7254]
+
Tue Jan 31 11:58:51 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* ext/tk/lib/multi-tk.rb: add MultiTkIp#eval and bg_eval.
@@ -36,6 +57,21 @@ Tue Jan 31 11:58:51 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* ext/tk/lib/tk/namespace.rb: TkNamespace#eval was enbugged at the
last commit. Now it will return a proper object.
+Tue Jan 31 08:07:02 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (int_upto): return an enumerator if no block is
+ attached to the method.
+
+ * numeric.c (int_downto): ditto.
+
+ * numeric.c (int_dotimes): ditto.
+
+ * enum.c (enum_first): new method Enumerable#first to take first n
+ element from an enumerable.
+
+ * enum.c (enum_group_by): new method Enumerable#group_by that
+ groups enumerable values according to their block values.
+
Tue Jan 31 00:08:22 2006 Hirokazu Yamamoto <ocean@m2.ccsnet.ne.jp>
* ext/syck/rubyext.c (syck_resolver_transfer): workaround for SEGV.
diff --git a/enum.c b/enum.c
index cec178f..1cefb6d 100644
--- a/enum.c
+++ b/enum.c
@@ -17,12 +17,6 @@
VALUE rb_mEnumerable;
static ID id_each, id_eqq, id_cmp;
-VALUE
-rb_each(VALUE obj)
-{
- return rb_funcall(obj, id_each, 0, 0);
-}
-
static VALUE
grep_i(VALUE i, VALUE *arg)
{
@@ -68,7 +62,7 @@ enum_grep(VALUE obj, VALUE pat)
arg[0] = pat;
arg[1] = ary;
- rb_iterate(rb_each, obj, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)arg);
+ rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)arg);
return ary;
}
@@ -117,13 +111,13 @@ enum_count(int argc, VALUE *argv, VALUE obj)
rb_scan_args(argc, argv, "1", &item);
args[0] = item;
args[1] = 0;
- rb_iterate(rb_each, obj, count_i, (VALUE)&args);
+ rb_block_call(obj, id_each, 0, 0, count_i, (VALUE)&args);
return INT2NUM(args[1]);
}
else {
long n = 0;
- rb_iterate(rb_each, obj, count_iter_i, (VALUE)&n);
+ rb_block_call(obj, id_each, 0, 0, count_iter_i, (VALUE)&n);
return INT2NUM(n);
}
}
@@ -161,7 +155,7 @@ enum_find(int argc, VALUE *argv, VALUE obj)
rb_scan_args(argc, argv, "01", &if_none);
RETURN_ENUMERATOR(obj, argc, argv);
- rb_iterate(rb_each, obj, find_i, (VALUE)&memo);
+ rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)&memo);
if (memo != Qundef) {
return memo;
}
@@ -201,7 +195,7 @@ enum_find_all(VALUE obj)
RETURN_ENUMERATOR(obj, 0, 0);
ary = rb_ary_new();
- rb_iterate(rb_each, obj, find_all_i, ary);
+ rb_block_call(obj, id_each, 0, 0, find_all_i, ary);
return ary;
}
@@ -234,7 +228,7 @@ enum_reject(VALUE obj)
RETURN_ENUMERATOR(obj, 0, 0);
ary = rb_ary_new();
- rb_iterate(rb_each, obj, reject_i, ary);
+ rb_block_call(obj, id_each, 0, 0, reject_i, ary);
return ary;
}
@@ -276,7 +270,7 @@ enum_collect(VALUE obj)
RETURN_ENUMERATOR(obj, 0, 0);
ary = rb_ary_new();
- rb_iterate(rb_each, obj, collect_i, ary);
+ rb_block_call(obj, id_each, 0, 0, collect_i, ary);
return ary;
}
@@ -296,7 +290,7 @@ enum_to_a(VALUE obj)
{
VALUE ary = rb_ary_new();
- rb_iterate(rb_each, obj, collect_all, ary);
+ rb_block_call(obj, id_each, 0, 0, collect_all, ary);
return ary;
}
@@ -351,7 +345,7 @@ enum_inject(int argc, VALUE *argv, VALUE obj)
if (rb_scan_args(argc, argv, "01", &memo) == 0)
memo = Qundef;
- rb_iterate(rb_each, obj, inject_i, (VALUE)&memo);
+ rb_block_call(obj, id_each, 0, 0, inject_i, (VALUE)&memo);
if (memo == Qundef) return Qnil;
return memo;
}
@@ -389,11 +383,103 @@ enum_partition(VALUE obj)
ary[0] = rb_ary_new();
ary[1] = rb_ary_new();
- rb_iterate(rb_each, obj, partition_i, (VALUE)ary);
+ rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)ary);
return rb_assoc_new(ary[0], ary[1]);
}
+static VALUE
+group_by_i(VALUE i, VALUE hash)
+{
+ VALUE group = rb_yield(i);
+ VALUE values;
+
+ values = rb_hash_aref(hash, group);
+ if (NIL_P(values)) {
+ values = rb_ary_new3(1, i);
+ rb_hash_aset(hash, group, values);
+ }
+ else {
+ rb_ary_push(values, i);
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.group_by {| obj | block } => a_hash
+ *
+ * Returns a hash, which keys are evaluated result from the
+ * block, and values are arrays of elements in <i>enum</i>
+ * corresponding to the key.
+ *
+ * (1..6).group_by {|i| i%3} #=> {0=>[3, 6], 1=>[1, 4], 2=>[2, 5]}
+ *
+ */
+
+static VALUE
+enum_group_by(VALUE obj)
+{
+ VALUE hash;
+
+ RETURN_ENUMERATOR(obj, 0, 0);
+
+ hash = rb_hash_new();
+ rb_block_call(obj, id_each, 0, 0, group_by_i, hash);
+
+ return hash;
+}
+
+static VALUE
+first_i(VALUE i, VALUE *ary)
+{
+ if (NIL_P(ary[0])) {
+ ary[1] = i;
+ rb_iter_break();
+ }
+ else {
+ long n = NUM2LONG(ary[0]);
+
+ if (n <= 0) {
+ rb_iter_break();
+ }
+ rb_ary_push(ary[1], i);
+ n--;
+ ary[0] = INT2NUM(n);
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * enum.first -> obj or nil
+ * enum.first(n) -> an_array
+ *
+ * Returns the first element, or the first +n+ elements, of the enumerable.
+ * If the enumerable is empty, the first form returns <code>nil</code>, and the
+ * second form returns an empty array.
+ *
+ */
+
+static VALUE
+enum_first(int argc, VALUE *argv, VALUE obj)
+{
+ VALUE n, ary[2];
+
+ rb_scan_args(argc, argv, "01", &n);
+
+ if (NIL_P(n)) {
+ ary[0] = ary[1] = Qnil;
+ }
+ else {
+ ary[0] = n;
+ ary[1] = rb_ary_new2(NUM2LONG(n));
+ }
+ rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)ary);
+
+ return ary[1];
+}
+
/*
* call-seq:
* enum.sort => array
@@ -525,7 +611,7 @@ enum_sort_by(VALUE obj)
ary = rb_ary_new();
}
RBASIC(ary)->klass = 0;
- rb_iterate(rb_each, obj, sort_by_i, ary);
+ rb_block_call(obj, id_each, 0, 0, sort_by_i, ary);
if (RARRAY(ary)->len > 1) {
ruby_qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE), sort_by_cmp, 0);
}
@@ -581,7 +667,7 @@ enum_all(VALUE obj)
{
VALUE result = Qtrue;
- rb_iterate(rb_each, obj, rb_block_given_p() ? all_iter_i : all_i, (VALUE)&result);
+ rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? all_iter_i : all_i, (VALUE)&result);
return result;
}
@@ -628,7 +714,7 @@ enum_any(VALUE obj)
{
VALUE result = Qfalse;
- rb_iterate(rb_each, obj, rb_block_given_p() ? any_iter_i : any_i, (VALUE)&result);
+ rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? any_iter_i : any_i, (VALUE)&result);
return result;
}
@@ -681,7 +767,7 @@ enum_one(VALUE obj)
{
VALUE result = Qundef;
- rb_iterate(rb_each, obj, rb_block_given_p() ? one_iter_i : one_i, (VALUE)&result);
+ rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? one_iter_i : one_i, (VALUE)&result);
if (result == Qundef) return Qfalse;
return result;
}
@@ -726,7 +812,7 @@ enum_none(VALUE obj)
{
VALUE result = Qtrue;
- rb_iterate(rb_each, obj, rb_block_given_p() ? none_iter_i : none_i, (VALUE)&result);
+ rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? none_iter_i : none_i, (VALUE)&result);
return result;
}
@@ -784,7 +870,7 @@ enum_min(VALUE obj)
{
VALUE result = Qundef;
- rb_iterate(rb_each, obj, rb_block_given_p() ? min_ii : min_i, (VALUE)&result);
+ rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? min_ii : min_i, (VALUE)&result);
if (result == Qundef) return Qnil;
return result;
}
@@ -842,7 +928,7 @@ enum_max(VALUE obj)
{
VALUE result = Qundef;
- rb_iterate(rb_each, obj, rb_block_given_p() ? max_ii : max_i, (VALUE)&result);
+ rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? max_ii : max_i, (VALUE)&result);
if (result == Qundef) return Qnil;
return result;
}
@@ -884,7 +970,7 @@ enum_min_by(VALUE obj)
memo[0] = Qundef;
memo[1] = Qnil;
- rb_iterate(rb_each, obj, min_by_i, (VALUE)memo);
+ rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
return memo[1];
}
@@ -925,7 +1011,7 @@ enum_max_by(VALUE obj)
memo[0] = Qundef;
memo[1] = Qnil;
- rb_iterate(rb_each, obj, max_by_i, (VALUE)memo);
+ rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
return memo[1];
}
@@ -959,7 +1045,7 @@ enum_member(VALUE obj, VALUE val)
memo[0] = val;
memo[1] = Qfalse;
- rb_iterate(rb_each, obj, member_i, (VALUE)memo);
+ rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo);
return memo[1];
}
@@ -993,7 +1079,7 @@ enum_each_with_index(VALUE obj)
RETURN_ENUMERATOR(obj, 0, 0);
- rb_iterate(rb_each, obj, each_with_index_i, (VALUE)&memo);
+ rb_block_call(obj, id_each, 0, 0, each_with_index_i, (VALUE)&memo);
return obj;
}
@@ -1057,7 +1143,7 @@ enum_zip(int argc, VALUE *argv, VALUE obj)
memo[0] = result;
memo[1] = rb_ary_new4(argc, argv);
memo[2] = 0;
- rb_iterate(rb_each, obj, zip_i, (VALUE)memo);
+ rb_block_call(obj, id_each, 0, 0, zip_i, (VALUE)memo);
return result;
}
@@ -1094,6 +1180,8 @@ Init_Enumerable(void)
rb_define_method(rb_mEnumerable,"map", enum_collect, 0);
rb_define_method(rb_mEnumerable,"inject", enum_inject, -1);
rb_define_method(rb_mEnumerable,"partition", enum_partition, 0);
+ rb_define_method(rb_mEnumerable,"group_by", enum_group_by, 0);
+ rb_define_method(rb_mEnumerable,"first", enum_first, -1);
rb_define_method(rb_mEnumerable,"all?", enum_all, 0);
rb_define_method(rb_mEnumerable,"any?", enum_any, 0);
rb_define_method(rb_mEnumerable,"one?", enum_one, 0);
diff --git a/enumerator.c b/enumerator.c
index 7b3af9f..3321e71 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -32,18 +32,6 @@ proc_call(VALUE proc, VALUE args)
return rb_proc_call(proc, args);
}
-static VALUE
-method_call(VALUE method, VALUE args)
-{
- int argc = 0;
- VALUE *argv = 0;
- if (args) {
- argc = RARRAY(args)->len;
- argv = RARRAY(args)->ptr;
- }
- return rb_method_call(argc, argv, method);
-}
-
struct enumerator {
VALUE method;
VALUE proc;
@@ -168,7 +156,7 @@ enum_each_slice(VALUE obj, VALUE n)
args[0] = rb_ary_new2(size);
args[1] = (VALUE)size;
- rb_iterate(rb_each, obj, each_slice_i, (VALUE)args);
+ rb_block_call(obj, rb_intern("each"), 0, 0, each_slice_i, (VALUE)args);
ary = args[0];
if (RARRAY(ary)->len > 0) rb_yield(ary);
@@ -235,7 +223,7 @@ enum_each_cons(VALUE obj, VALUE n)
args[0] = rb_ary_new2(size);
args[1] = (VALUE)size;
- rb_iterate(rb_each, obj, each_cons_i, (VALUE)args);
+ rb_block_call(obj, rb_intern("each"), 0, 0, each_cons_i, (VALUE)args);
return Qnil;
}
@@ -315,14 +303,6 @@ rb_enumeratorize(VALUE obj, VALUE meth, int argc, VALUE *argv)
return enumerator_init(enumerator_allocate(rb_cEnumerator), obj, meth, argc, argv);
}
-static VALUE
-enumerator_iter(VALUE memo)
-{
- struct enumerator *e = (struct enumerator *)memo;
-
- return method_call(e->method, e->args);
-}
-
/*
* call-seq:
* enum.each {...}
@@ -335,8 +315,14 @@ static VALUE
enumerator_each(VALUE obj)
{
struct enumerator *e = enumerator_ptr(obj);
+ int argc = 0;
+ VALUE *argv = 0;
- return rb_iterate(enumerator_iter, (VALUE)e, e->iter, (VALUE)e);
+ if (e->args) {
+ argc = RARRAY(e->args)->len;
+ argv = RARRAY(e->args)->ptr;
+ }
+ return rb_block_call(e->method, rb_intern("call"), argc, argv, e->iter, (VALUE)e);
}
static VALUE
@@ -360,9 +346,17 @@ enumerator_with_index(VALUE obj)
{
struct enumerator *e = enumerator_ptr(obj);
VALUE memo = 0;
+ int argc = 0;
+ VALUE *argv = 0;
+
+ if (e->args) {
+ argc = RARRAY(e->args)->len;
+ argv = RARRAY(e->args)->ptr;
+ }
+ return rb_block_call(e->method, rb_intern("call"), argc, argv, e->iter, (VALUE)e);
- return rb_iterate(enumerator_iter, (VALUE)e,
- enumerator_with_index_i, (VALUE)&memo);
+ return rb_block_call(e->method, rb_intern("call"), argc, argv,
+ enumerator_with_index_i, (VALUE)&memo);
}
void
diff --git a/env.h b/env.h
index 9f14c2c..6834617 100644
--- a/env.h
+++ b/env.h
@@ -22,7 +22,7 @@ RUBY_EXTERN struct FRAME {
struct FRAME *prev;
struct FRAME *tmp;
struct RNode *node;
- int iter;
+ struct BLOCK *block;
int flags;
unsigned long uniq;
} *ruby_frame;
@@ -45,8 +45,8 @@ RUBY_EXTERN struct SCOPE {
#define SCOPE_DONT_RECYCLE 4
RUBY_EXTERN int ruby_in_eval;
-
-RUBY_EXTERN VALUE ruby_class;
+VALUE ruby_current_class_object(void);
+#define ruby_class ruby_current_class_object()
struct RVarmap {
struct RBasic super;
@@ -72,7 +72,6 @@ struct BLOCK {
struct SCOPE *scope;
VALUE klass;
struct RNode *cref;
- int iter;
int vmode;
int flags;
int uniq;
@@ -80,8 +79,6 @@ struct BLOCK {
VALUE orig_thread;
VALUE wrapper;
VALUE block_obj;
- struct BLOCK *outer;
- struct BLOCK *prev;
};
#define BLOCK_D_SCOPE 1
diff --git a/error.c b/error.c
index 74a7834..76c8829 100644
--- a/error.c
+++ b/error.c
@@ -961,7 +961,7 @@ Init_Exception(void)
rb_eIndexError = rb_define_class("IndexError", rb_eStandardError);
rb_eKeyError = rb_define_class("KeyError", rb_eIndexError);
rb_eRangeError = rb_define_class("RangeError", rb_eStandardError);
- rb_eNameError = rb_define_class("NameError", rb_eStandardError);
+ rb_eNameError = rb_define_class("NameError", rb_eException);
rb_define_method(rb_eNameError, "initialize", name_err_initialize, -1);
rb_define_method(rb_eNameError, "name", name_err_name, 0);
rb_define_method(rb_eNameError, "to_s", name_err_to_s, 0);
diff --git a/eval.c b/eval.c
index 11dea38..33e82af 100644
--- a/eval.c
+++ b/eval.c
@@ -240,8 +240,7 @@ static VALUE proc_invoke(VALUE,VALUE,VALUE,VALUE);
static VALUE proc_lambda(void);
static VALUE rb_f_binding(VALUE);
static void rb_f_END(void);
-static VALUE rb_f_block_given_p(void);
-static VALUE block_pass(VALUE,NODE*);
+static struct BLOCK *passing_block(VALUE,struct BLOCK*);
static VALUE rb_cMethod;
static VALUE rb_cUnboundMethod;
static VALUE umethod_bind(VALUE, VALUE);
@@ -721,13 +720,13 @@ static struct SCOPE *top_scope;
static unsigned long frame_unique = 0;
-#define PUSH_FRAME() do { \
+#define PUSH_FRAME(link) do { \
struct FRAME _frame; \
_frame.prev = ruby_frame; \
_frame.tmp = 0; \
_frame.node = ruby_current_node; \
- _frame.iter = ruby_iter->iter; \
_frame.argc = 0; \
+ _frame.block = (link)?ruby_frame->block:0;\
_frame.flags = 0; \
_frame.uniq = frame_unique++; \
ruby_frame = &_frame
@@ -737,22 +736,17 @@ static unsigned long frame_unique = 0;
ruby_frame = _frame.prev; \
} while (0)
-static struct BLOCK *ruby_block;
static unsigned long block_unique = 0;
-#define PUSH_BLOCK(v,b) do { \
+#define PUSH_BLOCK(v,iv,b) do { \
struct BLOCK _block; \
- _block.var = (v); \
+ _block.var = (iv); \
_block.body = (b); \
_block.self = self; \
_block.frame = *ruby_frame; \
- _block.klass = ruby_class; \
_block.cref = ruby_cref; \
_block.frame.node = ruby_current_node;\
_block.scope = ruby_scope; \
- _block.prev = ruby_block; \
- _block.outer = ruby_block; \
- _block.iter = ruby_iter->iter; \
_block.vmode = scope_vmode; \
_block.flags = BLOCK_D_SCOPE; \
_block.dyna_vars = ruby_dyna_vars; \
@@ -762,11 +756,9 @@ static unsigned long block_unique = 0;
if (b) { \
prot_tag->blkid = _block.uniq; \
} \
- ruby_block = &_block
+ (v) = &_block
-#define POP_BLOCK() \
- ruby_block = _block.prev; \
-} while (0)
+#define POP_BLOCK() } while (0)
struct RVarmap *ruby_dyna_vars;
#define PUSH_VARS() do { \
@@ -897,31 +889,9 @@ rb_svar(int cnt)
return &ruby_scope->local_vars[cnt];
}
-struct iter {
- int iter;
- struct iter *prev;
-};
-static struct iter *ruby_iter;
-
-#define ITER_NOT 0
-#define ITER_PRE 1
-#define ITER_CUR 2
-#define ITER_PAS 3
-
-#define PUSH_ITER(i) do { \
- struct iter _iter; \
- _iter.prev = ruby_iter; \
- _iter.iter = (i); \
- ruby_iter = &_iter
-
-#define POP_ITER() \
- ruby_iter = _iter.prev; \
-} while (0)
-
struct tag {
rb_jmpbuf_t buf;
struct FRAME *frame;
- struct iter *iter;
VALUE tag;
VALUE retval;
struct SCOPE *scope;
@@ -935,7 +905,6 @@ static struct tag *prot_tag;
struct tag _tag; \
_tag.retval = Qnil; \
_tag.frame = ruby_frame; \
- _tag.iter = ruby_iter; \
_tag.prev = prot_tag; \
_tag.scope = ruby_scope; \
_tag.tag = ptag; \
@@ -955,7 +924,6 @@ static struct tag *prot_tag;
#define JUMP_TAG(st) do { \
ruby_frame = prot_tag->frame; \
- ruby_iter = prot_tag->iter; \
ruby_longjmp(prot_tag->buf,(st)); \
} while (0)
@@ -977,16 +945,8 @@ static struct tag *prot_tag;
#define TAG_THREAD 0xa
#define TAG_MASK 0xf
-VALUE ruby_class;
static VALUE ruby_wrapper; /* security wrapper */
-#define PUSH_CLASS(c) do { \
- VALUE _class = ruby_class; \
- ruby_class = (c)
-
-#define POP_CLASS() ruby_class = _class; \
-} while (0)
-
static NODE *ruby_cref = 0;
static NODE *top_cref;
#define PUSH_CREF(c) ruby_cref = NEW_NODE(NODE_CREF,(c),0,ruby_cref)
@@ -1031,7 +991,6 @@ struct ruby_env {
struct FRAME *frame;
struct SCOPE *scope;
struct BLOCK *block;
- struct iter *iter;
struct tag *tag;
NODE *cref;
};
@@ -1067,7 +1026,7 @@ typedef enum calling_scope {
CALLING_SUPER,
} calling_scope_t;
-static VALUE rb_call(VALUE,VALUE,ID,int,const VALUE*,calling_scope_t);
+static VALUE rb_call(VALUE,VALUE,ID,int,const VALUE*,struct BLOCK*,calling_scope_t);
static VALUE module_setup(VALUE,NODE*);
static VALUE massign(VALUE,NODE*,VALUE,int);
@@ -1304,7 +1263,6 @@ ruby_init(void)
{
static int initialized = 0;
static struct FRAME frame;
- static struct iter iter;
int state;
if (initialized)
@@ -1315,7 +1273,6 @@ ruby_init(void)
#endif
ruby_frame = top_frame = &frame;
- ruby_iter = &iter;
#ifdef __MACOS__
rb_origenviron = 0;
@@ -1333,7 +1290,6 @@ ruby_init(void)
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
rb_call_inits();
- ruby_class = rb_cObject;
ruby_frame->self = ruby_top_self;
top_cref = rb_node_newnode(NODE_CREF,rb_cObject,0,0);
ruby_cref = top_cref;
@@ -1506,7 +1462,6 @@ ruby_cleanup(int ex)
ruby_safe_level = 0;
Init_stack((void*)&state);
PUSH_THREAD_TAG();
- PUSH_ITER(ITER_NOT);
if ((state = EXEC_TAG()) == 0) {
ruby_finalize_0();
if (ruby_errinfo) err = ruby_errinfo;
@@ -1519,7 +1474,6 @@ ruby_cleanup(int ex)
else if (ex == 0) {
ex = state;
}
- POP_ITER();
ruby_errinfo = err;
ex = error_handle(ex);
ruby_finalize_1();
@@ -1540,7 +1494,6 @@ ruby_exec_internal(void)
int state;
PUSH_THREAD_TAG();
- PUSH_ITER(ITER_NOT);
/* default visibility is private at toplevel */
SCOPE_SET(SCOPE_PRIVATE);
if ((state = EXEC_TAG()) == 0) {
@@ -1549,7 +1502,6 @@ ruby_exec_internal(void)
else if (state == TAG_THREAD) {
rb_thread_start_1();
}
- POP_ITER();
POP_THREAD_TAG();
return state;
}
@@ -1627,15 +1579,14 @@ rb_eval_string_wrap(const char *str, int *state)
VALUE wrapper = ruby_wrapper;
VALUE val;
- PUSH_CLASS(ruby_wrapper = rb_module_new());
ruby_top_self = rb_obj_clone(ruby_top_self);
rb_extend_object(ruby_top_self, ruby_wrapper);
- PUSH_FRAME();
+ PUSH_FRAME(Qfalse);
ruby_frame->callee = 0;
ruby_frame->this_func = 0;
ruby_frame->this_class = 0;
ruby_frame->self = self;
- PUSH_CREF(ruby_wrapper);
+ PUSH_CREF(ruby_wrapper = rb_module_new());
PUSH_SCOPE();
val = rb_eval_string_protect(str, &status);
@@ -1643,7 +1594,6 @@ rb_eval_string_wrap(const char *str, int *state)
POP_SCOPE();
POP_FRAME();
- POP_CLASS();
ruby_wrapper = wrapper;
if (state) {
*state = status;
@@ -1748,7 +1698,6 @@ rb_eval_cmd(VALUE cmd, VALUE arg, int level)
level = 4;
}
if (TYPE(cmd) != T_STRING) {
- PUSH_ITER(ITER_NOT);
PUSH_TAG(PROT_NONE);
ruby_safe_level = level;
if ((state = EXEC_TAG()) == 0) {
@@ -1756,14 +1705,13 @@ rb_eval_cmd(VALUE cmd, VALUE arg, int level)
}
ruby_safe_level = safe;
POP_TAG();
- POP_ITER();
if (state) JUMP_TAG(state);
return val;
}
saved_scope = ruby_scope;
ruby_scope = top_scope;
- PUSH_FRAME();
+ PUSH_FRAME(Qfalse);
ruby_frame->callee = 0;
ruby_frame->this_func = 0;
ruby_frame->this_class = 0;
@@ -1788,6 +1736,11 @@ rb_eval_cmd(VALUE cmd, VALUE arg, int level)
}
#define ruby_cbase (ruby_cref->nd_clss)
+VALUE
+ruby_current_class_object()
+{
+ return ruby_cbase;
+}
static VALUE
ev_const_defined(NODE *cref, ID id, VALUE self)
@@ -2175,22 +2128,6 @@ copy_node_scope(NODE *node, NODE *rval)
#define SETUP_ARGS(anode) SETUP_ARGS0(anode, anode->nd_alen)
-#define BEGIN_CALLARGS do {\
- struct BLOCK *tmp_block = ruby_block;\
- int tmp_iter = ruby_iter->iter;\
- switch (tmp_iter) {\
- case ITER_PRE:\
- ruby_block = ruby_block->outer;\
- case ITER_PAS:\
- tmp_iter = ITER_NOT;\
- }\
- PUSH_ITER(tmp_iter)
-
-#define END_CALLARGS \
- ruby_block = tmp_block;\
- POP_ITER();\
-} while (0)
-
#define MATCH_DATA *rb_svar(node->nd_cnt)
static const char* is_defined(VALUE, NODE*, char*, int);
@@ -2556,10 +2493,9 @@ call_trace_func(rb_event_t event, NODE *node, VALUE self, ID id, VALUE klass /*
}
tracing = 1;
prev = ruby_frame;
- PUSH_FRAME();
+ PUSH_FRAME(Qfalse);
*ruby_frame = *prev;
ruby_frame->prev = prev;
- ruby_frame->iter = 0; /* blocks not available anyway */
if (node) {
ruby_current_node = node;
@@ -2717,6 +2653,9 @@ NORETURN(static void return_jump(VALUE));
NORETURN(static void break_jump(VALUE));
NORETURN(static void unknown_node(NODE * volatile));
+static VALUE call_super(int, const VALUE*, struct BLOCK*);
+static VALUE call_super_0(VALUE, VALUE, ID mid, int argc, const VALUE*, struct BLOCK *);
+
static void
unknown_node(NODE *volatile node)
{
@@ -2765,7 +2704,11 @@ rb_eval(VALUE self, NODE *n)
goto again;
case NODE_POSTEXE:
+ PUSH_FRAME(Qtrue);
+ PUSH_BLOCK(ruby_frame->block, 0, node->nd_body);
rb_f_END();
+ POP_BLOCK();
+ POP_FRAME();
nd_set_type(node, NODE_NIL); /* exec just once */
result = Qnil;
break;
@@ -3003,72 +2946,17 @@ rb_eval(VALUE self, NODE *n)
if (state) JUMP_TAG(state);
RETURN(result);
- case NODE_BLOCK_PASS:
- result = block_pass(self, node);
- break;
-
case NODE_LAMBDA:
PUSH_TAG(PROT_LOOP);
- PUSH_BLOCK(node->nd_var, node->nd_body);
-
+ PUSH_FRAME(Qtrue);
+ PUSH_BLOCK(ruby_frame->block, node->nd_var, node->nd_body);
state = EXEC_TAG();
- PUSH_ITER(ITER_PRE);
- ruby_iter->iter = ruby_frame->iter = ITER_CUR;
result = proc_lambda();
- POP_ITER();
POP_BLOCK();
+ POP_FRAME();
POP_TAG();
break;
- case NODE_ITER:
- case NODE_FOR:
- {
- PUSH_TAG(PROT_LOOP);
- PUSH_BLOCK(node->nd_var, node->nd_body);
-
- state = EXEC_TAG();
- if (state == 0) {
- iter_retry:
- PUSH_ITER(ITER_PRE);
- if (nd_type(node) == NODE_ITER) {
- result = rb_eval(self, node->nd_iter);
- }
- else if (nd_type(node) == NODE_LAMBDA) {
- ruby_iter->iter = ruby_frame->iter = ITER_CUR;
- result = rb_block_proc();
- }
- else {
- VALUE recv;
-
- _block.flags &= ~BLOCK_D_SCOPE;
- BEGIN_CALLARGS;
- recv = rb_eval(self, node->nd_iter);
- END_CALLARGS;
- ruby_current_node = node;
- SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(recv),recv,each,0,0,CALLING_NORMAL);
- }
- POP_ITER();
- }
- else if (state == TAG_BREAK && TAG_DST()) {
- result = prot_tag->retval;
- state = 0;
- }
- else if (state == TAG_RETRY && ruby_block == &_block) {
- state = 0;
- goto iter_retry;
- }
- POP_BLOCK();
- POP_TAG();
- switch (state) {
- case 0:
- break;
- default:
- JUMP_TAG(state);
- }
- }
- break;
-
case NODE_BREAK:
break_jump(rb_eval(self, node->nd_stts));
break;
@@ -3275,7 +3163,6 @@ rb_eval(VALUE self, NODE *n)
calling_scope_t scope;
TMP_PROTECT;
- BEGIN_CALLARGS;
if (node->nd_recv == (NODE *)1) {
recv = self;
scope = CALLING_FCALL;
@@ -3285,29 +3172,167 @@ rb_eval(VALUE self, NODE *n)
scope = CALLING_NORMAL;
}
SETUP_ARGS(node->nd_args);
- END_CALLARGS;
ruby_current_node = node;
SET_CURRENT_SOURCE();
- rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,scope);
+ rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0,scope);
result = argv[argc-1];
}
break;
+ case NODE_FOR:
+ {
+ VALUE recv;
+ int state;
+ struct BLOCK *block;
+
+ PUSH_TAG(PROT_LOOP);
+ PUSH_BLOCK(block, node->nd_var, node->nd_body);
+ state = EXEC_TAG();
+ if (state == 0) {
+ for_retry:
+ block->flags &= ~BLOCK_D_SCOPE;
+ recv = rb_eval(self, node->nd_iter);
+ ruby_current_node = node;
+ SET_CURRENT_SOURCE();
+ result = rb_call(CLASS_OF(recv),recv,each,0,0,block,CALLING_NORMAL);
+ }
+ else if (state == TAG_BREAK && TAG_DST()) {
+ result = prot_tag->retval;
+ state = 0;
+ }
+ else if (state == TAG_RETRY) {
+ state = 0;
+ goto for_retry;
+ }
+ POP_BLOCK();
+ POP_TAG();
+ if (state) JUMP_TAG(state);
+ }
+ break;
+
+ case NODE_BLOCK_PASS:
+ {
+ VALUE recv = self;
+ calling_scope_t scope;
+ NODE *bpass = node;
+
+ PUSH_TAG(PROT_LOOP);
+ node = node->nd_iter; /* should be NODE_CALL */
+ switch (nd_type(node)) {
+ case NODE_CALL:
+ scope = CALLING_NORMAL; break;
+ case NODE_FCALL:
+ scope = CALLING_FCALL; break;
+ case NODE_VCALL:
+ scope = CALLING_VCALL; break;
+ case NODE_SUPER:
+ scope = CALLING_SUPER; break;
+ default:
+ /* error! */
+ unknown_node(node);
+ }
+ state = EXEC_TAG();
+ if (state == 0) {
+ struct BLOCK *block, _block;
+ int argc; VALUE *argv; /* used in SETUP_ARGS */
+ TMP_PROTECT;
+
+ block_pass_retry:
+ if (scope == CALLING_NORMAL) {
+ recv = rb_eval(self, node->nd_recv);
+ }
+ SETUP_ARGS(node->nd_args);
+ block = passing_block(rb_eval(self, bpass->nd_body), &_block);
+ ruby_current_node = node;
+ SET_CURRENT_SOURCE();
+ if (scope == CALLING_SUPER) {
+ result = call_super(argc, argv, block);
+ }
+ else {
+ result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,block,scope);
+ }
+ }
+ else if (state == TAG_BREAK && TAG_DST()) {
+ result = prot_tag->retval;
+ state = 0;
+ }
+ else if (state == TAG_RETRY) {
+ state = 0;
+ goto block_pass_retry;
+ }
+ POP_TAG();
+ if (state) JUMP_TAG(state);
+ }
+ break;
+
+ case NODE_ITER:
+ {
+ VALUE recv = self;
+ calling_scope_t scope;
+ struct BLOCK *block;
+
+ PUSH_TAG(PROT_LOOP);
+ PUSH_BLOCK(block, node->nd_var, node->nd_body);
+ node = node->nd_iter; /* should be NODE_CALL */
+ switch (nd_type(node)) {
+ case NODE_CALL:
+ scope = CALLING_NORMAL; break;
+ case NODE_FCALL:
+ scope = CALLING_FCALL; break;
+ case NODE_VCALL:
+ scope = CALLING_VCALL; break;
+ case NODE_SUPER:
+ scope = CALLING_SUPER; break;
+ default:
+ /* error! */
+ unknown_node(node);
+ }
+ state = EXEC_TAG();
+ if (state == 0) {
+ int argc; VALUE *argv; /* used in SETUP_ARGS */
+ TMP_PROTECT;
+
+ iter_retry:
+ if (scope == CALLING_NORMAL) {
+ recv = rb_eval(self, node->nd_recv);
+ }
+ SETUP_ARGS(node->nd_args);
+ ruby_current_node = node;
+ SET_CURRENT_SOURCE();
+ if (scope == CALLING_SUPER) {
+ result = call_super(argc, argv, block);
+ }
+ else {
+ result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,block,scope);
+ }
+ }
+ else if (state == TAG_BREAK && TAG_DST()) {
+ result = prot_tag->retval;
+ state = 0;
+ }
+ else if (state == TAG_RETRY) {
+ state = 0;
+ goto iter_retry;
+ }
+ POP_BLOCK();
+ POP_TAG();
+ if (state) JUMP_TAG(state);
+ }
+ break;
+
case NODE_CALL:
{
VALUE recv;
int argc; VALUE *argv; /* used in SETUP_ARGS */
TMP_PROTECT;
- BEGIN_CALLARGS;
recv = rb_eval(self, node->nd_recv);
SETUP_ARGS(node->nd_args);
- END_CALLARGS;
ruby_current_node = node;
SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,CALLING_NORMAL);
+ result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0,CALLING_NORMAL);
}
break;
@@ -3316,19 +3341,17 @@ rb_eval(VALUE self, NODE *n)
int argc; VALUE *argv; /* used in SETUP_ARGS */
TMP_PROTECT;
- BEGIN_CALLARGS;
SETUP_ARGS(node->nd_args);
- END_CALLARGS;
ruby_current_node = node;
SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,CALLING_FCALL);
+ result = rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,0,CALLING_FCALL);
}
break;
case NODE_VCALL:
SET_CURRENT_SOURCE();
- result = rb_call(CLASS_OF(self),self,node->nd_mid,0,0,CALLING_VCALL);
+ result = rb_call(CLASS_OF(self),self,node->nd_mid,0,0,0,CALLING_VCALL);
break;
case NODE_SUPER:
@@ -3363,9 +3386,7 @@ rb_eval(VALUE self, NODE *n)
}
}
else {
- BEGIN_CALLARGS;
SETUP_ARGS(node->nd_args);
- END_CALLARGS;
ruby_current_node = node;
}
@@ -3757,20 +3778,20 @@ rb_eval(VALUE self, NODE *n)
VALUE origin;
int noex;
- if (NIL_P(ruby_class)) {
+ if (NIL_P(ruby_cbase)) {
rb_raise(rb_eTypeError, "no class/module to add method");
}
- if (ruby_class == rb_cObject && node->nd_mid == init) {
+ if (ruby_cbase == rb_cObject && node->nd_mid == init) {
rb_warn("redefining Object#initialize may cause infinite loop");
}
if (node->nd_mid == __id__ || node->nd_mid == __send__) {
rb_warn("redefining `%s' may cause serious problem",
rb_id2name(node->nd_mid));
}
- rb_frozen_class_p(ruby_class);
- body = search_method(ruby_class, node->nd_mid, &origin);
+ rb_frozen_class_p(ruby_cbase);
+ body = search_method(ruby_cbase, node->nd_mid, &origin);
if (body){
- if (RTEST(ruby_verbose) && ruby_class == origin && body->nd_cnt == 0 && body->nd_body) {
+ if (RTEST(ruby_verbose) && ruby_cbase == origin && body->nd_cnt == 0 && body->nd_body) {
rb_warning("method redefined; discarding old %s", rb_id2name(node->nd_mid));
}
}
@@ -3784,14 +3805,14 @@ rb_eval(VALUE self, NODE *n)
else {
noex = NOEX_PUBLIC;
}
- if (body && origin == ruby_class && body->nd_body == 0) {
+ if (body && origin == ruby_cbase && body->nd_body == 0) {
noex |= NOEX_NOSUPER;
}
defn = copy_node_scope(node->nd_defn, ruby_cref);
- rb_add_method(ruby_class, node->nd_mid, defn, noex);
+ rb_add_method(ruby_cbase, node->nd_mid, defn, noex);
if (scope_vmode == SCOPE_MODFUNC) {
- rb_add_method(rb_singleton_class(ruby_class),
+ rb_add_method(rb_singleton_class(ruby_cbase),
node->nd_mid, defn, NOEX_PUBLIC);
}
result = Qnil;
@@ -3832,18 +3853,18 @@ rb_eval(VALUE self, NODE *n)
break;
case NODE_UNDEF:
- if (NIL_P(ruby_class)) {
+ if (NIL_P(ruby_cbase)) {
rb_raise(rb_eTypeError, "no class to undef method");
}
- rb_undef(ruby_class, rb_to_id(rb_eval(self, node->u2.node)));
+ rb_undef(ruby_cbase, rb_to_id(rb_eval(self, node->u2.node)));
result = Qnil;
break;
case NODE_ALIAS:
- if (NIL_P(ruby_class)) {
+ if (NIL_P(ruby_cbase)) {
rb_raise(rb_eTypeError, "no class to make alias");
}
- rb_alias(ruby_class, rb_to_id(rb_eval(self, node->u1.node)),
+ rb_alias(ruby_cbase, rb_to_id(rb_eval(self, node->u1.node)),
rb_to_id(rb_eval(self, node->u2.node)));
result = Qnil;
break;
@@ -4001,7 +4022,6 @@ module_setup(VALUE module, NODE *n)
frame.tmp = ruby_frame;
ruby_frame = &frame;
- PUSH_CLASS(module);
PUSH_SCOPE();
PUSH_VARS();
@@ -4028,7 +4048,6 @@ module_setup(VALUE module, NODE *n)
POP_CREF();
POP_VARS();
POP_SCOPE();
- POP_CLASS();
ruby_frame = frame.tmp;
EXEC_EVENT_HOOK(RUBY_EVENT_END, n, 0, ruby_frame->this_func,
@@ -4546,7 +4565,7 @@ static void
rb_raise_jump(VALUE mesg)
{
if (ruby_frame != top_frame) {
- PUSH_FRAME(); /* fake frame */
+ PUSH_FRAME(Qfalse); /* fake frame */
*ruby_frame = *_frame.prev->prev;
rb_longjmp(TAG_RAISE, mesg);
POP_FRAME();
@@ -4563,8 +4582,7 @@ rb_jump_tag(int tag)
int
rb_block_given_p(void)
{
- if (ruby_frame->iter == ITER_CUR && ruby_block)
- return Qtrue;
+ if (ruby_frame->block) return Qtrue;
return Qfalse;
}
@@ -4599,7 +4617,7 @@ rb_iterator_p(void)
static VALUE
rb_f_block_given_p(void)
{
- if (ruby_frame->prev && ruby_frame->prev->iter == ITER_CUR && ruby_block)
+ if (ruby_frame->prev && ruby_frame->prev->block)
return Qtrue;
return Qfalse;
}
@@ -4711,7 +4729,7 @@ rb_yield_0(VALUE val, VALUE self, VALUE klass /* OK */, int flags, int avalue)
rb_need_block();
PUSH_VARS();
- block = ruby_block;
+ block = ruby_frame->block;
frame = block->frame;
frame.prev = ruby_frame;
frame.node = cnode;
@@ -4724,7 +4742,6 @@ rb_yield_0(VALUE val, VALUE self, VALUE klass /* OK */, int flags, int avalue)
ruby_scope = block->scope;
old_vmode = scope_vmode;
scope_vmode = (flags & YIELD_PUBLIC_DEF) ? SCOPE_PUBLIC : block->vmode;
- ruby_block = block->prev;
if (block->flags & BLOCK_D_SCOPE) {
/* put place holder for dynamic (in-block) local variables */
ruby_dyna_vars = new_dvar(0, 0, block->dyna_vars);
@@ -4733,8 +4750,8 @@ rb_yield_0(VALUE val, VALUE self, VALUE klass /* OK */, int flags, int avalue)
/* FOR does not introduce new scope */
ruby_dyna_vars = block->dyna_vars;
}
- PUSH_CLASS(klass ? klass : block->klass);
- if (!klass) {
+ if (klass) PUSH_CREF(klass);
+ else {
self = block->self;
}
node = block->body;
@@ -4832,7 +4849,6 @@ rb_yield_0(VALUE val, VALUE self, VALUE klass /* OK */, int flags, int avalue)
}
ruby_current_node = node;
- PUSH_ITER(block->iter);
PUSH_TAG(lambda ? PROT_NONE : PROT_YIELD);
if ((state = EXEC_TAG()) == 0) {
redo:
@@ -4853,13 +4869,9 @@ rb_yield_0(VALUE val, VALUE self, VALUE klass /* OK */, int flags, int avalue)
struct BLOCK *data, _block;
Data_Get_Struct(block->block_obj, struct BLOCK, data);
_block = *data;
- _block.outer = ruby_block;
_block.uniq = block_unique++;
- ruby_block = &_block;
- PUSH_ITER(ITER_PRE);
- ruby_frame->iter = ITER_CUR;
+ ruby_frame->block = &_block;
result = (*node->nd_cfnc)(val, node->nd_tval, self);
- POP_ITER();
}
else {
result = (*node->nd_cfnc)(val, node->nd_tval, self);
@@ -4892,9 +4904,7 @@ rb_yield_0(VALUE val, VALUE self, VALUE klass /* OK */, int flags, int avalue)
}
}
POP_TAG();
- POP_ITER();
pop_state:
- POP_CLASS();
if (ruby_dyna_vars && (block->flags & BLOCK_D_SCOPE) &&
!FL_TEST(ruby_dyna_vars, DVAR_DONT_RECYCLE)) {
struct RVarmap *vars = ruby_dyna_vars;
@@ -4910,7 +4920,6 @@ rb_yield_0(VALUE val, VALUE self, VALUE klass /* OK */, int flags, int avalue)
}
}
POP_VARS();
- ruby_block = block;
ruby_frame = ruby_frame->prev;
ruby_cref = (NODE*)old_cref;
ruby_wrapper = old_wrapper;
@@ -4926,7 +4935,7 @@ rb_yield_0(VALUE val, VALUE self, VALUE klass /* OK */, int flags, int avalue)
struct tag *tt = prot_tag;
while (tt) {
- if (tt->tag == PROT_LOOP && tt->blkid == ruby_block->uniq) {
+ if (tt->tag == PROT_LOOP && tt->blkid == block->uniq) {
tt->dst = (VALUE)tt->frame->uniq;
tt->retval = result;
JUMP_TAG(TAG_BREAK);
@@ -5125,7 +5134,7 @@ assign(VALUE self, NODE *lhs, VALUE val, int pcall)
/* attr set */
ruby_current_node = lhs;
SET_CURRENT_SOURCE();
- rb_call(CLASS_OF(recv), recv, lhs->nd_mid, 1, &val, scope);
+ rb_call(CLASS_OF(recv), recv, lhs->nd_mid, 1, &val, 0, scope);
}
else {
/* array set */
@@ -5136,7 +5145,7 @@ assign(VALUE self, NODE *lhs, VALUE val, int pcall)
ruby_current_node = lhs;
SET_CURRENT_SOURCE();
rb_call(CLASS_OF(recv), recv, lhs->nd_mid,
- RARRAY(args)->len, RARRAY(args)->ptr, scope);
+ RARRAY(args)->len, RARRAY(args)->ptr, 0, scope);
}
}
break;
@@ -5155,12 +5164,12 @@ rb_iterate(VALUE (*it_proc)(VALUE), VALUE data1, VALUE (*bl_proc)(ANYARGS), VALU
NODE *node = NEW_IFUNC(bl_proc, data2);
VALUE self = ruby_top_self;
- PUSH_ITER(ITER_PRE);
PUSH_TAG(PROT_LOOP);
- PUSH_BLOCK(0, node);
+ PUSH_FRAME(Qtrue);
+ PUSH_BLOCK(ruby_frame->block, 0, node);
state = EXEC_TAG();
if (state == 0) {
- iter_retry:
+ iter_retry:
retval = (*it_proc)(data1);
}
else if (state == TAG_BREAK && TAG_DST()) {
@@ -5172,8 +5181,8 @@ rb_iterate(VALUE (*it_proc)(VALUE), VALUE data1, VALUE (*bl_proc)(ANYARGS), VALU
goto iter_retry;
}
POP_BLOCK();
+ POP_FRAME();
POP_TAG();
- POP_ITER();
switch (state) {
case 0:
@@ -5184,6 +5193,42 @@ rb_iterate(VALUE (*it_proc)(VALUE), VALUE data1, VALUE (*bl_proc)(ANYARGS), VALU
return retval;
}
+struct iter_method_arg {
+ VALUE obj;
+ ID mid;
+ int argc;
+ VALUE *argv;
+};
+
+static VALUE
+iterate_method(VALUE obj)
+{
+ struct iter_method_arg *arg;
+
+ arg = (struct iter_method_arg*)obj;
+ return rb_call(CLASS_OF(arg->obj), arg->obj, arg->mid, arg->argc, arg->argv,
+ ruby_frame->block, CALLING_FCALL);
+}
+
+VALUE
+rb_block_call(VALUE obj, ID mid, int argc, VALUE *argv, VALUE (*bl_proc)(ANYARGS), VALUE data2)
+{
+ struct iter_method_arg arg;
+
+ arg.obj = obj;
+ arg.mid = mid;
+ arg.argc = argc;
+ arg.argv = argv;
+ return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
+}
+
+VALUE
+rb_each(VALUE obj)
+{
+ return rb_call(CLASS_OF(obj), obj, rb_intern("each"), 0, 0,
+ ruby_frame->block, CALLING_FCALL);
+}
+
static int
handle_rescue(VALUE self, NODE *node)
{
@@ -5194,10 +5239,7 @@ handle_rescue(VALUE self, NODE *node)
return rb_obj_is_kind_of(ruby_errinfo, rb_eStandardError);
}
- BEGIN_CALLARGS;
SETUP_ARGS(node->nd_args);
- END_CALLARGS;
-
while (argc--) {
if (!rb_obj_is_kind_of(argv[0], rb_cModule)) {
rb_raise(rb_eTypeError, "class or module required for rescue clause");
@@ -5442,14 +5484,16 @@ rb_method_missing(int argc, const VALUE *argv, VALUE obj)
}
static VALUE
-method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status)
+method_missing(VALUE obj, ID id, int argc, const VALUE *argv,
+ struct BLOCK *block, int call_status)
{
VALUE *nargv;
last_call_status = call_status;
if (id == missing) {
- PUSH_FRAME();
+ PUSH_FRAME(Qfalse);
+ ruby_frame->block = block;
rb_method_missing(argc, argv, obj);
POP_FRAME();
}
@@ -5461,7 +5505,7 @@ method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status)
nargv[0] = ID2SYM(id);
MEMCPY(nargv+1, argv, VALUE, argc);
- return rb_funcall2(obj, missing, argc+1, nargv);
+ return rb_call(CLASS_OF(obj), obj, missing, argc+1, nargv, block, CALLING_FCALL);
}
static inline VALUE
@@ -5620,49 +5664,46 @@ formal_assign(VALUE recv, NODE *node, int argc, const VALUE *argv, VALUE *local_
return i;
}
+#define PUSH_METHOD_FRAME() \
+ PUSH_FRAME(Qfalse);\
+ ruby_frame->callee = id;\
+ ruby_frame->this_func = oid;\
+ ruby_frame->this_class = (flags & NOEX_NOSUPER)?0:klass;\
+ ruby_frame->self = recv;\
+ ruby_frame->argc = argc;\
+ ruby_frame->block = block;\
+ ruby_frame->flags = (flags & NOEX_RECV) ? FRAME_FUNC : 0;\
+
static VALUE
rb_call0(VALUE klass, VALUE recv, ID id, ID oid,
- int argc /* OK */, const VALUE *argv /* OK */, NODE *volatile body, int flags)
+ int argc /* OK */, const VALUE *argv /* OK */,
+ struct BLOCK *block,
+ NODE *volatile body, int flags)
{
NODE *b2; /* OK */
volatile VALUE result = Qnil;
- int itr;
static int tick;
volatile VALUE args;
volatile int safe = -1;
TMP_PROTECT;
- switch (ruby_iter->iter) {
- case ITER_PRE:
- case ITER_PAS:
- itr = ITER_CUR;
- break;
- case ITER_CUR:
- default:
- itr = ITER_NOT;
- break;
- }
-
if ((++tick & 0xff) == 0) {
CHECK_INTS; /* better than nothing */
stack_check();
rb_gc_finalize_deferred();
}
if (argc < 0) {
- argc = -argc-1;
- args = rb_ary_concat(rb_ary_new4(argc, argv), splat_value(argv[argc]));
- argc = RARRAY(args)->len;
- argv = RARRAY(args)->ptr;
- }
- PUSH_ITER(itr);
- PUSH_FRAME();
- ruby_frame->callee = id;
- ruby_frame->this_func = oid;
- ruby_frame->this_class = (flags & NOEX_NOSUPER)?0:klass;
- ruby_frame->self = recv;
- ruby_frame->argc = argc;
- ruby_frame->flags = (flags & NOEX_RECV) ? FRAME_FUNC : 0;
+ VALUE tmp;
+ VALUE *nargv;
+ argc = -argc-1;
+ tmp = splat_value(argv[argc]);
+ nargv = TMP_ALLOC(argc + RARRAY(tmp)->len);
+ MEMCPY(nargv, argv, VALUE, argc);
+ MEMCPY(nargv+argc, RARRAY(tmp)->ptr, VALUE, RARRAY(tmp)->len);
+ argc += RARRAY(tmp)->len;
+ argv = nargv;
+ }
switch (nd_type(body)) {
case NODE_CFUNC:
{
@@ -5672,6 +5713,7 @@ rb_call0(VALUE klass, VALUE recv, ID id, ID oid,
rb_bug("bad argc (%d) specified for `%s(%s)'",
len, rb_class2name(klass), rb_id2name(id));
}
+ PUSH_METHOD_FRAME();
if (event_hooks) {
int state;
@@ -5690,6 +5732,7 @@ rb_call0(VALUE klass, VALUE recv, ID id, ID oid,
else {
result = call_cfunc(body->nd_cfnc, recv, len, argc, argv);
}
+ POP_FRAME();
}
break;
@@ -5708,12 +5751,14 @@ rb_call0(VALUE klass, VALUE recv, ID id, ID oid,
break;
case NODE_ZSUPER: /* visibility override */
- result = rb_call_super(argc, argv);
+ result = call_super_0(klass, recv, oid, argc, argv, block);
break;
case NODE_BMETHOD:
+ PUSH_METHOD_FRAME();
ruby_frame->flags |= FRAME_DMETH;
result = proc_invoke(body->nd_cval, rb_ary_new4(argc, argv), recv, klass);
+ POP_FRAME();
break;
case NODE_SCOPE:
@@ -5722,12 +5767,12 @@ rb_call0(VALUE klass, VALUE recv, ID id, ID oid,
VALUE *local_vars; /* OK */
NODE *saved_cref = 0;
+ PUSH_METHOD_FRAME();
PUSH_SCOPE();
if (body->nd_rval) {
saved_cref = ruby_cref;
ruby_cref = (NODE*)body->nd_rval;
}
- PUSH_CLASS(ruby_cbase);
if (body->nd_tbl) {
local_vars = TMP_ALLOC(body->nd_tbl[0]+1);
*local_vars++ = (VALUE)body;
@@ -5777,13 +5822,13 @@ rb_call0(VALUE klass, VALUE recv, ID id, ID oid,
}
POP_TAG();
POP_VARS();
- POP_CLASS();
POP_SCOPE();
ruby_cref = saved_cref;
if (safe >= 0) ruby_safe_level = safe;
if (event_hooks) {
EXEC_EVENT_HOOK(RUBY_EVENT_RETURN, body, recv, id, klass);
}
+ POP_FRAME();
switch (state) {
case 0:
break;
@@ -5807,14 +5852,13 @@ rb_call0(VALUE klass, VALUE recv, ID id, ID oid,
unknown_node(body);
break;
}
- POP_FRAME();
- POP_ITER();
return result;
}
static VALUE
rb_call(VALUE klass, VALUE recv, ID mid,
- int argc /* OK */, const VALUE *argv /* OK */, calling_scope_t scope)
+ int argc /* OK */, const VALUE *argv /* OK */, struct BLOCK *block,
+ calling_scope_t scope)
{
NODE *body; /* OK */
int noex;
@@ -5823,13 +5867,14 @@ rb_call(VALUE klass, VALUE recv, ID mid,
if (!klass) {
rb_raise(rb_eNotImpError, "method `%s' called on terminated object (%p)",
- rb_id2name(mid), recv);
+ rb_id2name(mid), (void*)recv);
}
/* is it in the method cache? */
ent = cache + EXPR1(klass, mid);
if (ent->mid == mid && ent->klass == klass) {
if (!ent->method)
- return method_missing(recv, mid, argc, argv, scope==CALLING_VCALL?CSTAT_VCALL:0);
+ return method_missing(recv, mid, argc, argv, block,
+ scope==CALLING_VCALL?CSTAT_VCALL:0);
klass = ent->origin;
id = ent->mid0;
noex = ent->noex;
@@ -5837,15 +5882,15 @@ rb_call(VALUE klass, VALUE recv, ID mid,
}
else if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) {
if (scope == CALLING_SUPER) {
- return method_missing(recv, mid, argc, argv, CSTAT_SUPER);
+ return method_missing(recv, mid, argc, argv, block, CSTAT_SUPER);
}
- return method_missing(recv, mid, argc, argv, scope==CALLING_VCALL?CSTAT_VCALL:0);
+ return method_missing(recv, mid, argc, argv, block, scope==CALLING_VCALL?CSTAT_VCALL:0);
}
if (mid != missing && scope == CALLING_NORMAL) {
/* receiver specified form for private method */
if (noex & NOEX_PRIVATE)
- return method_missing(recv, mid, argc, argv, CSTAT_PRIV);
+ return method_missing(recv, mid, argc, argv, block, CSTAT_PRIV);
/* self must be kind of a specified form for protected method */
if (noex & NOEX_PROTECTED) {
@@ -5855,13 +5900,13 @@ rb_call(VALUE klass, VALUE recv, ID mid,
defined_class = RBASIC(defined_class)->klass;
}
if (!rb_obj_is_kind_of(ruby_frame->self, rb_class_real(defined_class)))
- return method_missing(recv, mid, argc, argv, CSTAT_PROT);
+ return method_missing(recv, mid, argc, argv, block, CSTAT_PROT);
}
}
if (scope > CALLING_NORMAL) { /* pass receiver info */
noex |= NOEX_RECV;
}
- return rb_call0(klass, recv, mid, id, argc, argv, body, noex);
+ return rb_call0(klass, recv, mid, id, argc, argv, block, body, noex);
}
VALUE
@@ -5873,7 +5918,7 @@ rb_apply(VALUE recv, ID mid, VALUE args)
argc = RARRAY(args)->len; /* Assigns LONG, but argc is INT */
argv = ALLOCA_N(VALUE, argc);
MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);
- return rb_call(CLASS_OF(recv), recv, mid, argc, argv, CALLING_FCALL);
+ return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 0, CALLING_FCALL);
}
static VALUE
@@ -5884,9 +5929,8 @@ send_funcall(int argc, VALUE *argv, VALUE recv, calling_scope_t scope)
if (argc == 0) rb_raise(rb_eArgError, "no method name given");
vid = *argv++; argc--;
- PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
- vid = rb_call(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, scope);
- POP_ITER();
+ vid = rb_call(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv,
+ ruby_frame->block, scope);
return vid;
}
@@ -5917,8 +5961,14 @@ send_funcall(int argc, VALUE *argv, VALUE recv, calling_scope_t scope)
static VALUE
rb_f_send(int argc, VALUE *argv, VALUE recv)
{
- calling_scope_t scope = (ruby_frame->flags & FRAME_FUNC) ? CALLING_FCALL : CALLING_NORMAL;
+ calling_scope_t scope;
+ if (ruby_frame->flags & FRAME_FUNC) {
+ scope = CALLING_FCALL;
+ }
+ else {
+ scope = CALLING_NORMAL;
+ }
return send_funcall(argc, argv, recv, scope);
}
@@ -5961,42 +6011,47 @@ rb_funcall(VALUE recv, ID mid, int n, ...)
argv = 0;
}
- return rb_call(CLASS_OF(recv), recv, mid, n, argv, CALLING_FCALL);
+ return rb_call(CLASS_OF(recv), recv, mid, n, argv, 0, CALLING_FCALL);
}
VALUE
rb_funcall2(VALUE recv, ID mid, int argc, const VALUE *argv)
{
- return rb_call(CLASS_OF(recv), recv, mid, argc, argv, CALLING_FCALL);
+ return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 0, CALLING_FCALL);
}
VALUE
rb_funcall3(VALUE recv, ID mid, int argc, const VALUE *argv)
{
- return rb_call(CLASS_OF(recv), recv, mid, argc, argv, CALLING_NORMAL);
+ return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 0, CALLING_NORMAL);
}
-VALUE
-rb_call_super(int argc, const VALUE *argv)
+static VALUE
+call_super_0(VALUE klass, VALUE self, ID mid,
+ int argc, const VALUE *argv, struct BLOCK *block)
{
- VALUE result, self, klass;
+ if (RCLASS(klass)->super == 0) {
+ return method_missing(self, mid, argc, argv, block, CSTAT_SUPER);
+ }
+
+ return rb_call(RCLASS(klass)->super, self, mid, argc, argv, block, CALLING_SUPER);
+}
+static VALUE
+call_super(int argc, const VALUE *argv, struct BLOCK *block)
+{
if (ruby_frame->this_class == 0) {
rb_name_error(ruby_frame->callee, "calling `super' from `%s' is prohibited",
rb_id2name(ruby_frame->this_func));
}
+ return call_super_0(ruby_frame->this_class, ruby_frame->self,
+ ruby_frame->this_func, argc, argv, block);
+}
- self = ruby_frame->self;
- klass = ruby_frame->this_class;
- if (RCLASS(klass)->super == 0) {
- return method_missing(self, ruby_frame->this_func, argc, argv, CSTAT_SUPER);
- }
-
- PUSH_ITER(ruby_iter->iter ? ITER_PRE : ITER_NOT);
- result = rb_call(RCLASS(klass)->super, self, ruby_frame->this_func, argc, argv, CALLING_SUPER);
- POP_ITER();
-
- return result;
+VALUE
+rb_call_super(int argc, const VALUE *argv)
+{
+ return call_super(argc, argv, ruby_frame->block);
}
static VALUE
@@ -6137,14 +6192,12 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line)
struct BLOCK *data = NULL;
volatile VALUE result = Qnil;
struct SCOPE * volatile old_scope;
- struct BLOCK * volatile old_block;
struct RVarmap * volatile old_dyna_vars;
VALUE volatile old_cref;
int volatile old_vmode;
volatile VALUE old_wrapper;
struct FRAME frame;
NODE *nodesave = ruby_current_node;
- volatile int iter = ruby_frame->iter;
volatile int safe = ruby_safe_level;
int state;
@@ -6161,8 +6214,6 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line)
ruby_frame = &(frame);
old_scope = ruby_scope;
ruby_scope = data->scope;
- old_block = ruby_block;
- ruby_block = data->prev;
old_dyna_vars = ruby_dyna_vars;
ruby_dyna_vars = data->dyna_vars;
old_vmode = scope_vmode;
@@ -6178,22 +6229,15 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line)
}
self = data->self;
- ruby_frame->iter = data->iter;
- }
- else {
- if (ruby_frame->prev) {
- ruby_frame->iter = ruby_frame->prev->iter;
- }
}
if (file == 0) {
ruby_set_current_source();
file = ruby_sourcefile;
line = ruby_sourceline;
}
- PUSH_CLASS(ruby_cbase);
ruby_in_eval++;
- if (TYPE(ruby_class) == T_ICLASS) {
- ruby_class = RBASIC(ruby_class)->klass;
+ if (TYPE(ruby_cbase) == T_ICLASS) {
+ ruby_cbase = RBASIC(ruby_cbase)->klass;
}
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
@@ -6211,9 +6255,7 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line)
result = eval_node(self, node);
}
POP_TAG();
- POP_CLASS();
ruby_in_eval--;
- ruby_safe_level = safe;
if (!NIL_P(scope)) {
int dont_recycle = ruby_scope->flags & SCOPE_DONT_RECYCLE;
@@ -6221,7 +6263,6 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line)
ruby_cref = (NODE*)old_cref;
ruby_frame = frame.tmp;
ruby_scope = old_scope;
- ruby_block = old_block;
ruby_dyna_vars = old_dyna_vars;
data->vmode = scope_vmode; /* write back visibility mode */
scope_vmode = old_vmode;
@@ -6238,9 +6279,6 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line)
}
}
}
- else {
- ruby_frame->iter = iter;
- }
ruby_current_node = nodesave;
ruby_set_current_source();
if (state) {
@@ -6315,7 +6353,7 @@ rb_f_eval(int argc, VALUE *argv, VALUE self)
VALUE val;
prev = ruby_frame;
- PUSH_FRAME();
+ PUSH_FRAME(Qfalse);
*ruby_frame = *prev->prev;
ruby_frame->prev = prev;
val = eval(self, src, scope, file, line);
@@ -6328,23 +6366,20 @@ rb_f_eval(int argc, VALUE *argv, VALUE self)
/* function to call func under the specified class/module context */
static VALUE
-exec_under(VALUE (*func) (VALUE), VALUE under, VALUE cbase, VALUE args)
+exec_under(VALUE (*func) (VALUE), VALUE under, VALUE args)
{
VALUE val = Qnil; /* OK */
int state;
int mode;
struct FRAME *f = ruby_frame;
- PUSH_CLASS(under);
- PUSH_FRAME();
+ PUSH_CREF(under);
+ PUSH_FRAME(Qtrue);
ruby_frame->self = f->self;
ruby_frame->callee = f->callee;
ruby_frame->this_func = f->this_func;
ruby_frame->this_class = f->this_class;
ruby_frame->argc = f->argc;
- if (cbase) {
- PUSH_CREF(cbase);
- }
mode = scope_vmode;
SCOPE_SET(SCOPE_PUBLIC);
@@ -6353,10 +6388,9 @@ exec_under(VALUE (*func) (VALUE), VALUE under, VALUE cbase, VALUE args)
val = (*func)(args);
}
POP_TAG();
- if (cbase) POP_CREF();
+ POP_CREF();
SCOPE_SET(mode);
POP_FRAME();
- POP_CLASS();
if (state) JUMP_TAG(state);
return val;
@@ -6390,7 +6424,7 @@ eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
args[1] = src;
args[2] = (VALUE)file;
args[3] = (VALUE)line;
- return exec_under(eval_under_i, under, under, (VALUE)args);
+ return exec_under(eval_under_i, under, (VALUE)args);
}
static VALUE
@@ -6402,7 +6436,7 @@ yield_under_i(VALUE arg)
avalue = Qfalse;
args[0] = args[1];
}
- return rb_yield_0(args[0], args[1], ruby_class, YIELD_PUBLIC_DEF, avalue);
+ return rb_yield_0(args[0], args[1], ruby_cbase, YIELD_PUBLIC_DEF, avalue);
}
/* block eval under the class/module context */
@@ -6412,7 +6446,7 @@ yield_under(VALUE under, VALUE self, VALUE values)
VALUE args[4];
args[0] = values;
args[1] = self;
- return exec_under(yield_under_i, under, 0, (VALUE)args);
+ return exec_under(yield_under_i, under, (VALUE)args);
}
static VALUE
@@ -6605,22 +6639,19 @@ rb_load(VALUE fname, int wrap)
ruby_errinfo = Qnil; /* ensure */
PUSH_VARS();
- PUSH_CLASS(ruby_wrapper);
ruby_cref = top_cref;
if (!wrap) {
rb_secure(4); /* should alter global state */
- ruby_class = rb_cObject;
ruby_wrapper = 0;
}
else {
/* load in anonymous module as toplevel */
- ruby_class = ruby_wrapper = rb_module_new();
+ ruby_wrapper = rb_module_new();
self = rb_obj_clone(ruby_top_self);
rb_extend_object(self, ruby_wrapper);
PUSH_CREF(ruby_wrapper);
}
- PUSH_ITER(ITER_NOT);
- PUSH_FRAME();
+ PUSH_FRAME(Qfalse);
ruby_frame->callee = 0;
ruby_frame->this_func = 0;
ruby_frame->this_class = 0;
@@ -6659,7 +6690,7 @@ rb_load(VALUE fname, int wrap)
ruby_current_node = last_node;
ruby_sourcefile = 0;
ruby_set_current_source();
- if (ruby_scope->flags == SCOPE_ALLOCA && ruby_class == rb_cObject) {
+ if (ruby_scope->flags == SCOPE_ALLOCA && ruby_cbase == rb_cObject) {
if (ruby_scope->local_tbl) /* toplevel was empty */
free(ruby_scope->local_tbl);
}
@@ -6668,8 +6699,6 @@ rb_load(VALUE fname, int wrap)
ruby_cref = saved_cref;
POP_SCOPE();
POP_FRAME();
- POP_ITER();
- POP_CLASS();
POP_VARS();
ruby_wrapper = wrapper;
if (ruby_nerrs > 0) {
@@ -7319,9 +7348,7 @@ rb_mod_include(int argc, VALUE *argv, VALUE module)
void
rb_obj_call_init(VALUE obj, int argc, VALUE *argv)
{
- PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
- rb_funcall2(obj, init, argc, argv);
- POP_ITER();
+ rb_call(CLASS_OF(obj), obj, init, argc, argv, ruby_frame->block, CALLING_FCALL);
}
void
@@ -7545,8 +7572,7 @@ rb_mark_end_proc(void)
static void
call_end_proc(VALUE data)
{
- PUSH_ITER(ITER_NOT);
- PUSH_FRAME();
+ PUSH_FRAME(Qfalse);
ruby_frame->self = ruby_frame->prev->self;
ruby_frame->node = 0;
ruby_frame->callee = 0;
@@ -7554,15 +7580,12 @@ call_end_proc(VALUE data)
ruby_frame->this_class = 0;
proc_invoke(data, rb_ary_new2(0), Qundef, 0);
POP_FRAME();
- POP_ITER();
}
static void
rb_f_END(void)
{
- PUSH_FRAME();
- ruby_frame->argc = 0;
- ruby_frame->iter = ITER_CUR;
+ PUSH_FRAME(Qfalse);
rb_set_end_proc(call_end_proc, rb_block_proc());
POP_FRAME();
}
@@ -7884,7 +7907,7 @@ blk_mark(struct BLOCK *data)
rb_gc_mark((VALUE)data->cref);
rb_gc_mark(data->wrapper);
rb_gc_mark(data->block_obj);
- data = data->prev;
+ data = data->frame.block;
}
}
@@ -7909,7 +7932,7 @@ blk_free(struct BLOCK *data)
while (data) {
frame_free(&data->frame);
tmp = data;
- data = data->prev;
+ data = data->frame.block;
free(tmp);
}
}
@@ -7930,23 +7953,28 @@ frame_dup(struct FRAME *frame)
}
static void
-blk_copy_prev(struct BLOCK *block)
+dvar_nail_down(struct RVarmap *vars)
+{
+ while (vars) {
+ if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
+ FL_SET(vars, DVAR_DONT_RECYCLE);
+ vars = vars->next;
+ }
+}
+
+static void
+blk_nail_down(struct BLOCK *block)
{
struct BLOCK *tmp;
- struct RVarmap* vars;
- while (block->prev) {
+ dvar_nail_down(block->dyna_vars);
+ while (block->frame.block) {
tmp = ALLOC_N(struct BLOCK, 1);
- MEMCPY(tmp, block->prev, struct BLOCK, 1);
+ MEMCPY(tmp, block->frame.block, struct BLOCK, 1);
scope_dup(tmp->scope);
frame_dup(&tmp->frame);
-
- for (vars = tmp->dyna_vars; vars; vars = vars->next) {
- if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
- FL_SET(vars, DVAR_DONT_RECYCLE);
- }
-
- block->prev = tmp;
+ dvar_nail_down(tmp->dyna_vars);
+ block->frame.block = tmp;
block = tmp;
}
}
@@ -7957,13 +7985,7 @@ blk_dup(struct BLOCK *dup, struct BLOCK *orig)
{
MEMCPY(dup, orig, struct BLOCK, 1);
frame_dup(&dup->frame);
-
- if (dup->iter) {
- blk_copy_prev(dup);
- }
- else {
- dup->prev = 0;
- }
+ blk_nail_down(dup);
}
/*
@@ -7980,6 +8002,7 @@ proc_clone(VALUE self)
bind = Data_Make_Struct(rb_obj_class(self),struct BLOCK,blk_mark,blk_free,data);
CLONESETUP(bind, self);
blk_dup(data, orig);
+ if (orig->block_obj) data->block_obj = bind;
return bind;
}
@@ -8020,39 +8043,26 @@ proc_dup(VALUE self)
static VALUE
rb_f_binding(VALUE self)
{
- struct BLOCK *data, *p;
- struct RVarmap *vars;
+ struct BLOCK *data;
VALUE bind;
- PUSH_BLOCK(0,0);
+ PUSH_FRAME(Qtrue);
+ PUSH_BLOCK(ruby_frame->block,0,0);
bind = Data_Make_Struct(rb_cBinding,struct BLOCK,blk_mark,blk_free,data);
- *data = *ruby_block;
+ *data = *ruby_frame->block;
data->orig_thread = rb_thread_current();
data->wrapper = ruby_wrapper;
- data->iter = rb_f_block_given_p();
frame_dup(&data->frame);
if (ruby_frame->prev) {
data->frame.callee = ruby_frame->prev->callee;
data->frame.this_func = ruby_frame->prev->this_func;
data->frame.this_class = ruby_frame->prev->this_class;
}
-
- if (data->iter) {
- blk_copy_prev(data);
- }
- else {
- data->prev = 0;
- }
-
- for (p = data; p; p = p->prev) {
- for (vars = p->dyna_vars; vars; vars = vars->next) {
- if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
- FL_SET(vars, DVAR_DONT_RECYCLE);
- }
- }
+ blk_nail_down(data);
scope_dup(data->scope);
POP_BLOCK();
+ POP_FRAME();
return bind;
}
@@ -8094,12 +8104,14 @@ bind_eval(int argc, VALUE *argv, VALUE bind)
#define SAFE_LEVEL_MAX PROC_TMASK
#define proc_safe_level_p(data) (RBASIC(data)->flags & PROC_SAFE_SAVED)
+#define proc_delete_safe_level(data) FL_UNSET(data, PROC_SAFE_SAVED)
static void
proc_save_safe_level(VALUE data)
{
int safe = ruby_safe_level;
if (safe > PROC_TMAX) safe = PROC_TMAX;
+ FL_UNSET(data, PROC_TMASK);
FL_SET(data, (safe << PROC_TSHIFT) & PROC_TMASK);
FL_SET(data, PROC_SAFE_SAVED);
}
@@ -8118,55 +8130,48 @@ proc_set_safe_level(VALUE data)
}
static VALUE
-proc_alloc(VALUE klass, int proc)
+proc_alloc(VALUE klass, int lambda)
{
volatile VALUE block;
- struct BLOCK *data, *p;
- struct RVarmap *vars;
+ struct FRAME *frame = ruby_frame;
+ struct BLOCK *data;
if (!rb_block_given_p() && !rb_f_block_given_p()) {
rb_raise(rb_eArgError, "tried to create Proc object without a block");
}
- if (proc && !rb_block_given_p()) {
- rb_warn("tried to create Proc object without a block");
- }
-
- if (!proc && ruby_block->block_obj) {
- VALUE obj = ruby_block->block_obj;
- if (CLASS_OF(obj) != klass) {
- obj = proc_clone(obj);
- RBASIC(obj)->klass = klass;
+ if (!lambda) {
+ if (!rb_block_given_p()) {
+ frame = ruby_frame->prev;
+ }
+ else {
+ if (frame->block->block_obj) {
+ VALUE obj = frame->block->block_obj;
+ if (CLASS_OF(obj) != klass) {
+ obj = proc_clone(obj);
+ RBASIC(obj)->klass = klass;
+ }
+ return obj;
+ }
}
- return obj;
+ }
+ else if (!rb_block_given_p()) {
+ rb_warn("tried to create Proc object without a block");
}
block = Data_Make_Struct(klass, struct BLOCK, blk_mark, blk_free, data);
- *data = *ruby_block;
+ *data = *frame->block;
data->orig_thread = rb_thread_current();
data->wrapper = ruby_wrapper;
- data->iter = data->prev?Qtrue:Qfalse;
data->block_obj = block;
frame_dup(&data->frame);
- if (data->iter) {
- blk_copy_prev(data);
- }
- else {
- data->prev = 0;
- }
-
- for (p = data; p; p = p->prev) {
- for (vars = p->dyna_vars; vars; vars = vars->next) {
- if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
- FL_SET(vars, DVAR_DONT_RECYCLE);
- }
- }
+ blk_nail_down(data);
scope_dup(data->scope);
proc_save_safe_level(block);
- if (proc) {
+ if (lambda) {
data->flags |= BLOCK_LAMBDA;
}
else {
- ruby_block->block_obj = block;
+ frame->block->block_obj = block;
}
return block;
@@ -8247,7 +8252,6 @@ block_orphan(struct BLOCK *data)
static VALUE
proc_invoke(VALUE proc, VALUE args /* OK */, VALUE self, VALUE klass)
{
- struct BLOCK * volatile old_block;
struct BLOCK _block;
struct BLOCK *data;
volatile VALUE result = Qundef;
@@ -8273,12 +8277,12 @@ proc_invoke(VALUE proc, VALUE args /* OK */, VALUE self, VALUE klass)
ruby_wrapper = data->wrapper;
ruby_dyna_vars = data->dyna_vars;
/* PUSH BLOCK from data */
- old_block = ruby_block;
_block = *data;
_block.block_obj = bvar;
if (self != Qundef) _block.frame.self = self;
if (klass) _block.frame.this_class = klass;
_block.frame.argc = RARRAY(tmp)->len;
+ if (ruby_frame->flags & FRAME_DMETH)
if (_block.frame.argc && (ruby_frame->flags & FRAME_DMETH)) {
NEWOBJ(scope, struct SCOPE);
OBJSETUP(scope, tmp, T_SCOPE);
@@ -8286,10 +8290,8 @@ proc_invoke(VALUE proc, VALUE args /* OK */, VALUE self, VALUE klass)
scope->local_vars = _block.scope->local_vars;
_block.scope = scope;
}
- ruby_block = &_block;
-
- PUSH_ITER(ITER_CUR);
- ruby_frame->iter = ITER_CUR;
+ /* modify current frame */
+ ruby_frame->block = &_block;
PUSH_TAG((pcall&YIELD_LAMBDA_CALL) ? PROT_LAMBDA : PROT_NONE);
state = EXEC_TAG();
if (state == 0) {
@@ -8301,11 +8303,10 @@ proc_invoke(VALUE proc, VALUE args /* OK */, VALUE self, VALUE klass)
result = prot_tag->retval;
}
POP_TAG();
- POP_ITER();
- ruby_block = old_block;
ruby_wrapper = old_wrapper;
POP_VARS();
- ruby_safe_level = safe;
+ if (proc_safe_level_p(proc))
+ ruby_safe_level = safe;
switch (state) {
case 0:
@@ -8555,13 +8556,7 @@ proc_binding(VALUE proc)
bind = Data_Make_Struct(rb_cBinding,struct BLOCK,blk_mark,blk_free,data);
MEMCPY(data, orig, struct BLOCK, 1);
frame_dup(&data->frame);
-
- if (data->iter) {
- blk_copy_prev(data);
- }
- else {
- data->prev = 0;
- }
+ blk_nail_down(data);
return bind;
}
@@ -8578,9 +8573,7 @@ rb_block_pass(VALUE (*func) (VALUE), VALUE arg, VALUE proc)
volatile int safe = ruby_safe_level;
if (NIL_P(proc)) {
- PUSH_ITER(ITER_NOT);
result = (*func)(arg);
- POP_ITER();
return result;
}
if (!rb_obj_is_proc(proc)) {
@@ -8597,25 +8590,17 @@ rb_block_pass(VALUE (*func) (VALUE), VALUE arg, VALUE proc)
rb_raise(rb_eSecurityError, "Insecure: tainted block value");
}
- if (ruby_block && ruby_block->block_obj == proc) {
- PUSH_ITER(ITER_PAS);
- result = (*func)(arg);
- POP_ITER();
- return result;
+ if (ruby_frame->block && ruby_frame->block->block_obj == proc) {
+ return (*func)(arg);
}
Data_Get_Struct(proc, struct BLOCK, data);
orphan = block_orphan(data);
- /* PUSH BLOCK from data */
+ PUSH_FRAME(Qtrue);
_block = *data;
- _block.outer = ruby_block;
if (orphan) _block.uniq = block_unique++;
- ruby_block = &_block;
- PUSH_ITER(ITER_PRE);
- if (ruby_frame->iter == ITER_NOT)
- ruby_frame->iter = ITER_PRE;
-
+ ruby_frame->block = &_block;
PUSH_TAG(PROT_LOOP);
state = EXEC_TAG();
if (state == 0) {
@@ -8634,8 +8619,7 @@ rb_block_pass(VALUE (*func) (VALUE), VALUE arg, VALUE proc)
goto retry;
}
POP_TAG();
- POP_ITER();
- ruby_block = _block.outer;
+ POP_FRAME();
if (proc_safe_level_p(proc)) ruby_safe_level = safe;
switch (state) {/* escape from orphan block */
@@ -8657,20 +8641,35 @@ struct block_arg {
NODE *iter;
};
-static VALUE
-call_block(struct block_arg *arg)
+static struct BLOCK *
+passing_block(VALUE proc, struct BLOCK *blockp)
{
- return rb_eval(arg->self, arg->iter);
-}
+ VALUE b;
+ struct BLOCK *data;
+ volatile int orphan;
-static VALUE
-block_pass(VALUE self, NODE *node)
-{
- struct block_arg arg;
- arg.self = self;
- arg.iter = node->nd_iter;
- return rb_block_pass((VALUE (*)(VALUE))call_block,
- (VALUE)&arg, rb_eval(self, node->nd_body));
+ if (NIL_P(proc)) return 0;
+ if (!rb_obj_is_proc(proc)) {
+ b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
+ if (!rb_obj_is_proc(b)) {
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Proc)",
+ rb_obj_classname(proc));
+ }
+ proc = b;
+ }
+
+ if (ruby_safe_level >= 1 && OBJ_TAINTED(proc) &&
+ ruby_safe_level > proc_get_safe_level(proc)) {
+ rb_raise(rb_eSecurityError, "Insecure: tainted block value");
+ }
+
+ Data_Get_Struct(proc, struct BLOCK, data);
+ orphan = block_orphan(data);
+ if (!orphan) return data;
+
+ *blockp = *data;
+ if (orphan) blockp->uniq = block_unique++;
+ return blockp;
}
static void
@@ -8944,9 +8943,8 @@ rb_method_call(int argc, VALUE *argv, VALUE method)
else {
safe = data->safe_level;
}
- PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
- result = rb_call0(data->klass,data->recv,data->id,data->oid,argc,argv,data->body,safe);
- POP_ITER();
+ result = rb_call0(data->klass,data->recv,data->id,data->oid,
+ argc,argv,ruby_frame->block,data->body,safe);
return result;
}
@@ -9230,13 +9228,8 @@ mproc(VALUE method)
{
VALUE proc;
- /* emulate ruby's method call */
- PUSH_ITER(ITER_CUR);
- PUSH_FRAME();
proc = rb_block_proc();
- POP_FRAME();
- POP_ITER();
-
+ proc_delete_safe_level(proc);
return proc;
}
@@ -9380,7 +9373,7 @@ rb_mod_define_method(int argc, VALUE *argv, VALUE mod)
struct BLOCK *block;
body = proc_clone(body);
- proc_save_safe_level(body);
+ proc_delete_safe_level(body);
Data_Get_Struct(body, struct BLOCK, block);
block->frame.callee = id;
block->frame.this_func = id;
@@ -9761,7 +9754,6 @@ struct thread {
struct BLOCK *block;
struct iter *iter;
struct tag *tag;
- VALUE klass;
VALUE wrapper;
NODE *cref;
struct ruby_env *anchor;
@@ -9892,9 +9884,7 @@ rb_trap_eval(VALUE cmd, int sig, int safe)
arg[2] = (VALUE)safe;
THREAD_COPY_STATUS(curr_thread, &save);
rb_thread_ready(curr_thread);
- PUSH_ITER(ITER_NOT);
val = rb_protect(run_trap_eval, (VALUE)&arg, &state);
- POP_ITER();
THREAD_COPY_STATUS(&save, curr_thread);
if (state) {
@@ -9980,7 +9970,6 @@ thread_mark(rb_thread_t th)
rb_gc_mark(th->thread);
if (th->join) rb_gc_mark(th->join->thread);
- rb_gc_mark(th->klass);
rb_gc_mark(th->wrapper);
rb_gc_mark((VALUE)th->cref);
@@ -10027,7 +10016,7 @@ thread_mark(rb_thread_t th)
while (block) {
block = ADJ(block);
rb_gc_mark_frame(&block->frame);
- block = block->prev;
+ block = block->frame.block;
}
}
@@ -10182,14 +10171,11 @@ rb_thread_save_context(rb_thread_t th)
th->frame = ruby_frame;
th->scope = ruby_scope;
ruby_scope->flags |= SCOPE_DONT_RECYCLE;
- th->klass = ruby_class;
th->wrapper = ruby_wrapper;
th->cref = ruby_cref;
th->dyna_vars = ruby_dyna_vars;
- th->block = ruby_block;
th->flags &= THREAD_FLAGS_MASK;
th->flags |= (rb_trap_immediate<<8) | scope_vmode;
- th->iter = ruby_iter;
th->tag = prot_tag;
th->tracing = tracing;
th->errinfo = ruby_errinfo;
@@ -10263,13 +10249,10 @@ rb_thread_restore_context_0(rb_thread_t th, int exit, void *vp)
rb_trap_immediate = 0; /* inhibit interrupts from here */
ruby_frame = th->frame;
ruby_scope = th->scope;
- ruby_class = th->klass;
ruby_wrapper = th->wrapper;
ruby_cref = th->cref;
ruby_dyna_vars = th->dyna_vars;
- ruby_block = th->block;
scope_vmode = th->flags&SCOPE_MASK;
- ruby_iter = th->iter;
prot_tag = th->tag;
tracing = th->tracing;
ruby_errinfo = th->errinfo;
@@ -10436,7 +10419,7 @@ rb_thread_deadlock(void)
char msg[21+SIZEOF_LONG*2];
VALUE e;
- sprintf(msg, "Thread(%p): deadlock", curr_thread->thread);
+ sprintf(msg, "Thread(%p): deadlock", (void*)curr_thread->thread);
e = rb_exc_new2(rb_eFatal, msg);
if (curr_thread == main_thread) {
rb_exc_raise(e);
@@ -10963,10 +10946,10 @@ rb_thread_join(rb_thread_t th, double limit)
if (!rb_thread_dead(th)) {
if (th == curr_thread)
rb_raise(rb_eThreadError, "thread %p tried to join itself",
- th->thread);
+ (void*)th->thread);
if ((th->wait_for & WAIT_JOIN) && th->join == curr_thread)
rb_raise(rb_eThreadError, "Thread#join: deadlock %p - mutual join(%p)",
- curr_thread->thread, th->thread);
+ (void*)curr_thread->thread, (void*)th->thread);
if (curr_thread->status == THREAD_TO_KILL)
last_status = THREAD_TO_KILL;
if (limit == 0) return Qfalse;
@@ -11582,12 +11565,10 @@ rb_thread_group(VALUE thread)
\
th->frame = 0;\
th->scope = 0;\
- th->klass = 0;\
th->wrapper = 0;\
th->cref = ruby_cref;\
th->dyna_vars = ruby_dyna_vars;\
th->block = 0;\
- th->iter = 0;\
th->tag = 0;\
th->tracing = 0;\
th->errinfo = Qnil;\
@@ -11717,9 +11698,7 @@ push_thread_anchor(struct ruby_env *ip)
{
ip->tag = prot_tag;
ip->frame = ruby_frame;
- ip->block = ruby_block;
ip->scope = ruby_scope;
- ip->iter = ruby_iter;
ip->cref = ruby_cref;
ip->prev = curr_thread->anchor;
curr_thread->anchor = ip;
@@ -11791,12 +11770,8 @@ rb_thread_start_0(VALUE (*fn)(ANYARGS), VALUE arg, rb_thread_t th)
ruby_longjmp((prot_tag = ip->tag)->buf, TAG_THREAD);
}
- if (ruby_block) { /* should nail down higher blocks */
- struct BLOCK dummy;
-
- dummy.prev = ruby_block;
- blk_copy_prev(&dummy);
- saved_block = ruby_block = dummy.prev;
+ if (ruby_frame->block) { /* should nail down higher blocks */
+ blk_nail_down(ruby_frame->block);
}
scope_dup(ruby_scope);
@@ -11881,15 +11856,12 @@ rb_thread_start_1(void)
int state;
ruby_frame = ip->frame;
- ruby_block = ip->block;
ruby_scope = ip->scope;
- ruby_iter = ip->iter;
ruby_cref = ip->cref;
ruby_dyna_vars = ((struct BLOCK *)DATA_PTR(proc))->dyna_vars;
- PUSH_FRAME();
+ PUSH_FRAME(Qtrue);
*ruby_frame = *ip->frame;
ruby_frame->prev = ip->frame;
- ruby_frame->iter = ITER_CUR;
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
if (THREAD_SAVE_CONTEXT(th) == 0) {
@@ -11923,7 +11895,7 @@ rb_thread_yield(VALUE arg, rb_thread_t th)
{
const ID *tbl;
- scope_dup(ruby_block->scope);
+ scope_dup(ruby_frame->block->scope);
tbl = ruby_scope->local_tbl;
if (tbl) {
@@ -11936,7 +11908,7 @@ rb_thread_yield(VALUE arg, rb_thread_t th)
}
rb_dvar_push('_', Qnil);
rb_dvar_push('~', Qnil);
- ruby_block->dyna_vars = ruby_dyna_vars;
+ ruby_frame->block->dyna_vars = ruby_dyna_vars;
return rb_yield_0(arg, 0, 0, YIELD_LAMBDA_CALL, Qtrue);
}
@@ -12519,7 +12491,7 @@ rb_thread_inspect(VALUE thread)
const char *status = thread_status_name(th->status);
VALUE str;
- str = rb_sprintf("#<%s:%p %s>", cname, thread, status);
+ str = rb_sprintf("#<%s:%p %s>", cname, (void*)thread, status);
OBJ_INFECT(str, thread);
return str;
@@ -12999,16 +12971,12 @@ rb_f_catch(VALUE dmy, VALUE tag)
return val;
}
-static VALUE
-catch_i(VALUE tag)
-{
- return rb_funcall(Qnil, rb_intern("catch"), 1, tag);
-}
-
VALUE
rb_catch(const char *tag, VALUE (*func)(ANYARGS), VALUE data)
{
- return rb_iterate((VALUE(*)(VALUE))catch_i, ID2SYM(rb_intern(tag)), func, data);
+ VALUE vtag = ID2SYM(rb_intern(tag));
+
+ return rb_block_call(Qnil, rb_intern("catch"), 1, &vtag, func, data);
}
/*
diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c
index 5573cb4..6e03e0e 100644
--- a/ext/dbm/dbm.c
+++ b/ext/dbm/dbm.c
@@ -426,20 +426,10 @@ fdbm_invert(obj)
return hash;
}
-static VALUE each_pair _((VALUE));
+static VALUE fdbm_store(VALUE,VALUE,VALUE);
static VALUE
-each_pair(obj)
- VALUE obj;
-{
- return rb_funcall(obj, rb_intern("each_pair"), 0, 0);
-}
-
-static VALUE fdbm_store _((VALUE,VALUE,VALUE));
-
-static VALUE
-update_i(pair, dbm)
- VALUE pair, dbm;
+update_i(VALUE pair, VALUE dbm)
{
Check_Type(pair, T_ARRAY);
if (RARRAY(pair)->len < 2) {
@@ -450,19 +440,17 @@ update_i(pair, dbm)
}
static VALUE
-fdbm_update(obj, other)
- VALUE obj, other;
+fdbm_update(VALUE obj, VALUE other)
{
- rb_iterate(each_pair, other, update_i, obj);
+ rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
return obj;
}
static VALUE
-fdbm_replace(obj, other)
- VALUE obj, other;
+fdbm_replace(VALUE obj, VALUE other)
{
fdbm_clear(obj);
- rb_iterate(each_pair, other, update_i, obj);
+ rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
return obj;
}
diff --git a/ext/gdbm/gdbm.c b/ext/gdbm/gdbm.c
index a5d86e7..cb59ff3 100644
--- a/ext/gdbm/gdbm.c
+++ b/ext/gdbm/gdbm.c
@@ -530,13 +530,6 @@ fgdbm_invert(obj)
static VALUE each_pair _((VALUE));
-static VALUE
-each_pair(obj)
- VALUE obj;
-{
- return rb_funcall(obj, rb_intern("each_pair"), 0, 0);
-}
-
static VALUE fgdbm_store _((VALUE,VALUE,VALUE));
static VALUE
@@ -555,7 +548,7 @@ static VALUE
fgdbm_update(obj, other)
VALUE obj, other;
{
- rb_iterate(each_pair, other, update_i, obj);
+ rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
return obj;
}
@@ -564,7 +557,7 @@ fgdbm_replace(obj, other)
VALUE obj, other;
{
fgdbm_clear(obj);
- rb_iterate(each_pair, other, update_i, obj);
+ rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
return obj;
}
diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c
index cebbd91..37224d8 100644
--- a/ext/iconv/iconv.c
+++ b/ext/iconv/iconv.c
@@ -522,7 +522,7 @@ get_iconv_opt(struct rb_iconv_opt_t *opt, VALUE options)
opt->transliterate = Qundef;
opt->discard_ilseq = Qundef;
if (!NIL_P(options)) {
- rb_iterate(rb_each, options, get_iconv_opt_i, (VALUE)opt);
+ rb_block_call(options, rb_intern("each"), 0, 0, get_iconv_opt_i, (VALUE)opt);
}
}
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index 8d6bd01..e374964 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -678,7 +678,7 @@ static VALUE
join_der(VALUE enumerable)
{
VALUE str = rb_str_new(0, 0);
- rb_iterate(rb_each, enumerable, join_der_i, str);
+ rb_block_call(enumerable, rb_intern("each"), 0, 0, join_der_i, str);
return str;
}
diff --git a/ext/openssl/ossl_config.c b/ext/openssl/ossl_config.c
index ef89fdf..bf2db6b 100644
--- a/ext/openssl/ossl_config.c
+++ b/ext/openssl/ossl_config.c
@@ -246,7 +246,7 @@ static VALUE
ossl_config_set_section(VALUE self, VALUE section, VALUE hash)
{
VALUE arg[2] = { self, section };
- rb_iterate(rb_each, hash, set_conf_section_i, (VALUE)arg);
+ rb_block_call(hash, rb_intern("each"), 0, 0, set_conf_section_i, (VALUE)arg);
return hash;
}
diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c
index 38a7dce..0f6ffc0 100644
--- a/ext/openssl/ossl_pkcs7.c
+++ b/ext/openssl/ossl_pkcs7.c
@@ -583,7 +583,7 @@ ossl_pkcs7_set_certificates(VALUE self, VALUE ary)
certs = pkcs7_get_certs_or_crls(self, 1);
while((cert = sk_X509_pop(certs))) X509_free(cert);
- rb_iterate(rb_each, ary, ossl_pkcs7_set_certs_i, self);
+ rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_certs_i, self);
return ary;
}
@@ -623,7 +623,7 @@ ossl_pkcs7_set_crls(VALUE self, VALUE ary)
crls = pkcs7_get_certs_or_crls(self, 0);
while((crl = sk_X509_CRL_pop(crls))) X509_CRL_free(crl);
- rb_iterate(rb_each, ary, ossl_pkcs7_set_crls_i, self);
+ rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_crls_i, self);
return ary;
}
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 30ab5bd..aab6477 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -324,7 +324,7 @@ ossl_sslctx_setup(VALUE self)
val = ossl_sslctx_get_extra_cert(self);
if(!NIL_P(val)){
- rb_iterate(rb_each, val, ossl_sslctx_add_extra_chain_cert_i, self);
+ rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self);
}
/* private key may be bundled in certificate file. */
diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c
index 989e28a..ece8bb8 100644
--- a/ext/openssl/ossl_x509name.c
+++ b/ext/openssl/ossl_x509name.c
@@ -125,7 +125,7 @@ ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
VALUE args;
if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE;
args = rb_ary_new3(2, self, template);
- rb_iterate(rb_each, tmp, ossl_x509name_init_i, args);
+ rb_block_call(tmp, rb_intern("each"), 0, 0, ossl_x509name_init_i, args);
}
else{
unsigned char *p;
diff --git a/ext/sdbm/init.c b/ext/sdbm/init.c
index f3e215e..9311a72 100644
--- a/ext/sdbm/init.c
+++ b/ext/sdbm/init.c
@@ -406,13 +406,6 @@ fsdbm_invert(obj)
static VALUE each_pair _((VALUE));
-static VALUE
-each_pair(obj)
- VALUE obj;
-{
- return rb_funcall(obj, rb_intern("each_pair"), 0, 0);
-}
-
static VALUE fsdbm_store _((VALUE,VALUE,VALUE));
static VALUE
@@ -431,7 +424,7 @@ static VALUE
fsdbm_update(obj, other)
VALUE obj, other;
{
- rb_iterate(each_pair, other, update_i, obj);
+ rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
return obj;
}
@@ -440,7 +433,7 @@ fsdbm_replace(obj, other)
VALUE obj, other;
{
fsdbm_clear(obj);
- rb_iterate(each_pair, other, update_i, obj);
+ rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
return obj;
}
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index d315526..c29d4bc 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -70,7 +70,7 @@
#endif
#include "sockport.h"
-static int do_not_reverse_lookup = 1;
+static int do_not_reverse_lookup = 0;
#define FMODE_NOREVLOOKUP 0x100
VALUE rb_cBasicSocket;
diff --git a/ext/syck/rubyext.c b/ext/syck/rubyext.c
index 078de4f..150ae14 100644
--- a/ext/syck/rubyext.c
+++ b/ext/syck/rubyext.c
@@ -571,7 +571,7 @@ yaml_org_handler( n, ref )
VALUE dup = rb_funcall( tmph, s_dup, 0 );
tmp = rb_ary_reverse( tmp );
rb_ary_push( tmp, obj );
- rb_iterate( rb_each, tmp, syck_merge_i, dup );
+ rb_block_call(tmp, rb_intern("each"), 0, 0, syck_merge_i, dup);
obj = dup;
skip_aset = 1;
}
@@ -1006,7 +1006,7 @@ syck_resolver_node_import( self, node )
VALUE dup = rb_funcall( end, s_dup, 0 );
v = rb_ary_reverse( v );
rb_ary_push( v, obj );
- rb_iterate( rb_each, v, syck_merge_i, dup );
+ rb_block_call(v, rb_intern("each"), 0, 0, syck_merge_i, dup);
obj = dup;
skip_aset = 1;
}
@@ -1175,7 +1175,7 @@ syck_resolver_transfer( self, type, val )
}
else if ( !NIL_P( obj ) && rb_obj_is_instance_of( val, rb_cHash ) )
{
- rb_iterate( rb_each, val, syck_set_ivars, obj );
+ rb_block_call(val, rb_intern("each"), 0, 0, syck_set_ivars, obj);
}
}
else
diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c
index fde5d2d..2e6b49e 100644
--- a/ext/win32ole/win32ole.c
+++ b/ext/win32ole/win32ole.c
@@ -2218,7 +2218,7 @@ ole_invoke(argc, argv, self, wFlags)
op.dp.cArgs = cNamedArgs + argc - 2;
op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1);
op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs);
- rb_iterate(rb_each, param, hash2named_arg, (VALUE)&op);
+ rb_block_call(param, rb_intern("each"), 0, 0, hash2named_arg, (VALUE)&op);
pDispID = ALLOCA_N(DISPID, cNamedArgs + 1);
op.pNamedArgs[0] = ole_mb2wc(StringValuePtr(cmd), -1);
diff --git a/io.c b/io.c
index 8e0a4e7..44e2a11 100644
--- a/io.c
+++ b/io.c
@@ -5241,7 +5241,7 @@ argf_each_line(int argc, VALUE *argv, VALUE self)
if (TYPE(current_file) != T_FILE) {
for (;;) {
if (!next_argv()) return argf;
- rb_iterate(rb_each, current_file, rb_yield, 0);
+ rb_block_call(current_file, rb_intern("each"), 0, 0, rb_yield, 0);
next_p = 1;
}
}
diff --git a/lib/optparse.rb b/lib/optparse.rb
index 0850ffd..6d1daeb 100644
--- a/lib/optparse.rb
+++ b/lib/optparse.rb
@@ -1457,8 +1457,8 @@ class OptionParser
: (({block}))
yielded with the found value when succeeded.
=end #'#"#`#
- def search(id, k)
- visit(:search, id, k) do |k|
+ def search(id, key)
+ visit(:search, id, key) do |k|
return k unless block_given?
return yield(k)
end
diff --git a/node.h b/node.h
index 5022ac0..7ee4931 100644
--- a/node.h
+++ b/node.h
@@ -336,7 +336,7 @@ typedef struct RNode {
#define NEW_ERRINFO() NEW_NODE(NODE_ERRINFO,0,0,0)
#define NEW_DEFINED(e) NEW_NODE(NODE_DEFINED,e,0,0)
#define NEW_PREEXE(b) NEW_SCOPE(b)
-#define NEW_POSTEXE() NEW_NODE(NODE_POSTEXE,0,0,0)
+#define NEW_POSTEXE(b) NEW_NODE(NODE_POSTEXE,0,b,0)
#define NEW_BMETHOD(b) NEW_NODE(NODE_BMETHOD,0,0,b)
#define NEW_ATTRASGN(r,m,a) NEW_NODE(NODE_ATTRASGN,r,m,a)
#define NEW_PRELUDE(p,b) NEW_NODE(NODE_PRELUDE,p,b,0)
diff --git a/numeric.c b/numeric.c
index b036d06..3a0536e 100644
--- a/numeric.c
+++ b/numeric.c
@@ -2672,6 +2672,7 @@ fix_size(VALUE fix)
static VALUE
int_upto(VALUE from, VALUE to)
{
+ RETURN_ENUMERATOR(from, 1, &to);
if (FIXNUM_P(from) && FIXNUM_P(to)) {
long i, end;
@@ -2710,6 +2711,7 @@ int_upto(VALUE from, VALUE to)
static VALUE
int_downto(VALUE from, VALUE to)
{
+ RETURN_ENUMERATOR(from, 1, &to);
if (FIXNUM_P(from) && FIXNUM_P(to)) {
long i, end;
@@ -2749,6 +2751,7 @@ int_downto(VALUE from, VALUE to)
static VALUE
int_dotimes(VALUE num)
{
+ RETURN_ENUMERATOR(num, 0, 0);
if (FIXNUM_P(num)) {
long i, end;
diff --git a/parse.y b/parse.y
index 2b8af2f..41de56b 100644
--- a/parse.y
+++ b/parse.y
@@ -867,7 +867,7 @@ stmt : kALIAS fitem {lex_state = EXPR_FNAME;} fitem
rb_warn("END in method; use at_exit");
}
- $$ = NEW_ITER(0, NEW_POSTEXE(), $3);
+ $$ = NEW_POSTEXE($3);
/*%
if (in_def || in_single) {
rb_warn0("END in method; use at_exit");
diff --git a/ruby.h b/ruby.h
index 50ebea3..7a91b87 100644
--- a/ruby.h
+++ b/ruby.h
@@ -575,6 +575,7 @@ VALUE rb_yield_splat(VALUE);
int rb_block_given_p(void);
void rb_need_block(void);
VALUE rb_iterate(VALUE(*)(VALUE),VALUE,VALUE(*)(ANYARGS),VALUE);
+VALUE rb_iterate_method(VALUE,ID,VALUE,VALUE(*)(ANYARGS),VALUE);
VALUE rb_rescue(VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE);
VALUE rb_rescue2(VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE,...);
VALUE rb_ensure(VALUE(*)(ANYARGS),VALUE,VALUE(*)(ANYARGS),VALUE);
diff --git a/struct.c b/struct.c
index 1cc4d38..9a70908 100644
--- a/struct.c
+++ b/struct.c
@@ -667,21 +667,15 @@ rb_struct_values_at(int argc, VALUE *argv, VALUE s)
/*
* call-seq:
- * struct.select(fixnum, ... ) => array
* struct.select {|i| block } => array
*
- * The first form returns an array containing the elements in
- * <i>struct</i> corresponding to the given indices. The second
- * form invokes the block passing in successive elements from
+ * Invokes the block passing in successive elements from
* <i>struct</i>, returning an array containing those elements
* for which the block returns a true value (equivalent to
* <code>Enumerable#select</code>).
*
* Lots = Struct.new(:a, :b, :c, :d, :e, :f)
* l = Lots.new(11, 22, 33, 44, 55, 66)
- * l.select(1, 3, 5) #=> [22, 44, 66]
- * l.select(0, 2, 4) #=> [11, 33, 55]
- * l.select(-1, -3, -5) #=> [66, 44, 22]
* l.select {|v| (v % 2).zero? } #=> [22, 44, 66]
*/
diff --git a/test/ruby/envutil.rb b/test/ruby/envutil.rb
index cd9ad3c..cf7f6e9 100644
--- a/test/ruby/envutil.rb
+++ b/test/ruby/envutil.rb
@@ -1,11 +1,18 @@
module EnvUtil
def rubybin
+ unless ENV["RUBYOPT"]
+
+ end
if ruby = ENV["RUBY"]
return ruby
end
ruby = "ruby"
+ rubyexe = ruby+".exe"
3.times do
- if File.exist? ruby or File.exist? ruby+".exe"
+ if File.exist? ruby and File.executable? ruby and !File.directory? ruby
+ return File.expand_path(ruby)
+ end
+ if File.exist? rubyexe and File.executable? rubyexe
return File.expand_path(ruby)
end
ruby = File.join("..", ruby)
diff --git a/test/webrick/test_filehandler.rb b/test/webrick/test_filehandler.rb
index 703fde4..64b2fcf 100644
--- a/test/webrick/test_filehandler.rb
+++ b/test/webrick/test_filehandler.rb
@@ -9,7 +9,11 @@ class WEBrick::TestFileHandler < Test::Unit::TestCase
end
def get_res_body(res)
- return res.body.read rescue res.body
+ if defined? res.body.read
+ res.body.read
+ else
+ res.body
+ end
end
def make_range_request(range_spec)