summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--eval.c107
2 files changed, 64 insertions, 52 deletions
diff --git a/ChangeLog b/ChangeLog
index c2059e9680..1cf1b8987c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Wed Jun 28 01:48:23 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_eval): support splat in when expression list.
+ [ruby-dev:28822]
+
+ * eval.c (when_check): a new auxiliary function for case match.
+
+ * eval.c (when_cond): ditto.
+
Wed Jun 28 01:05:37 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* object.c (rb_cstr_to_dbl): should not skip '_' at the beginning
diff --git a/eval.c b/eval.c
index c08b98128f..e9775fa308 100644
--- a/eval.c
+++ b/eval.c
@@ -2674,6 +2674,48 @@ unknown_node(NODE *volatile node)
}
}
+static int
+when_cond(VALUE v1, VALUE v2)
+{
+ if (v1 == Qundef) {
+ return RTEST(v2);
+ }
+ return RTEST(rb_funcall2(v2, eqq, 1, &v1));
+}
+
+static int
+when_check(NODE *tag, VALUE val, VALUE self)
+{
+ VALUE elm;
+ long i;
+
+ switch (nd_type(tag)) {
+ case NODE_ARRAY:
+ while (tag) {
+ elm = rb_eval(self, tag->nd_head);
+ if (when_cond(val, elm)) {
+ return Qtrue;
+ }
+ tag = tag->nd_next;
+ }
+ break;
+ case NODE_SPLAT:
+ elm = svalue_to_avalue(rb_eval(self, tag->nd_head));
+ for (i=0; i<RARRAY(elm)->len; i++) {
+ if (when_cond(val, RARRAY(elm)->ptr[i])) {
+ return Qtrue;
+ }
+ }
+ break;
+ case NODE_ARGSCAT:
+ if (when_check(tag->nd_head, val, self)) return Qtrue;
+ return when_check(tag->nd_body, val, self);
+ default:
+ unknown_node(tag);
+ }
+ return Qfalse;
+}
+
static VALUE
rb_eval(VALUE self, NODE *n)
{
@@ -2804,34 +2846,15 @@ rb_eval(VALUE self, NODE *n)
goto again;
case NODE_WHEN:
+ node = node->nd_body;
while (node) {
- NODE *tag;
-
if (nd_type(node) != NODE_WHEN) goto again;
- tag = node->nd_head;
- while (tag) {
- EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self,
- ruby_frame->this_func,
- ruby_frame->this_class);
- if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
- VALUE v = rb_eval(self, tag->nd_head->nd_head);
- long i;
-
- if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v);
- for (i=0; i<RARRAY(v)->len; i++) {
- if (RTEST(RARRAY(v)->ptr[i])) {
- node = node->nd_body;
- goto again;
- }
- }
- tag = tag->nd_next;
- continue;
- }
- if (RTEST(rb_eval(self, tag->nd_head))) {
- node = node->nd_body;
- goto again;
- }
- tag = tag->nd_next;
+ EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node->nd_head, self,
+ ruby_frame->this_func,
+ ruby_frame->this_class);
+ if (when_check(node->nd_head, Qundef, self)) {
+ node = node->nd_body;
+ goto again;
}
node = node->nd_next;
}
@@ -2844,35 +2867,15 @@ rb_eval(VALUE self, NODE *n)
val = rb_eval(self, node->nd_head);
node = node->nd_body;
while (node) {
- NODE *tag;
-
if (nd_type(node) != NODE_WHEN) {
goto again;
}
- tag = node->nd_head;
- while (tag) {
- EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self,
- ruby_frame->this_func,
- ruby_frame->this_class);
- if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
- VALUE v = rb_eval(self, tag->nd_head->nd_head);
- long i;
-
- if (TYPE(v) != T_ARRAY) v = rb_ary_to_ary(v);
- for (i=0; i<RARRAY(v)->len; i++) {
- if (RTEST(rb_funcall2(RARRAY(v)->ptr[i], eqq, 1, &val))){
- node = node->nd_body;
- goto again;
- }
- }
- tag = tag->nd_next;
- continue;
- }
- if (RTEST(rb_funcall2(rb_eval(self, tag->nd_head), eqq, 1, &val))) {
- node = node->nd_body;
- goto again;
- }
- tag = tag->nd_next;
+ EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node->nd_head, self,
+ ruby_frame->this_func,
+ ruby_frame->this_class);
+ if (when_check(node->nd_head, val, self)) {
+ node = node->nd_body;
+ goto again;
}
node = node->nd_next;
}