[前][次][番号順一覧][スレッド一覧]

ruby-changes:18166

From: nobu <ko1@a...>
Date: Mon, 13 Dec 2010 00:03:42 +0900 (JST)
Subject: [ruby-changes:18166] Ruby:r30187 (trunk): * compile.c (iseq_compile_each): fix for __goto__ and __label__

nobu	2010-12-12 23:45:30 +0900 (Sun, 12 Dec 2010)

  New Revision: 30187

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=30187

  Log:
    * compile.c (iseq_compile_each): fix for __goto__ and __label__
      where were totally broken.

  Modified files:
    trunk/ChangeLog
    trunk/compile.c
    trunk/iseq.h

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 30186)
+++ ChangeLog	(revision 30187)
@@ -1,3 +1,8 @@
+Sun Dec 12 23:45:27 2010  Nobuyoshi Nakada  <nobu@r...>
+
+	* compile.c (iseq_compile_each): fix for __goto__ and __label__
+	  where were totally broken.
+
 Sun Dec 12 22:45:43 2010  Nobuyoshi Nakada  <nobu@r...>
 
 	* common.mk (ID_H_INCLUDES): now id.h depends on vm_opts.h.
Index: iseq.h
===================================================================
--- iseq.h	(revision 30186)
+++ iseq.h	(revision 30187)
@@ -93,6 +93,9 @@
     int label_no;
     int node_level;
     const rb_compile_option_t *option;
+#if SUPPORT_JOKE
+    st_table *labels_table;
+#endif
 };
 
 /* defined? */
Index: compile.c
===================================================================
--- compile.c	(revision 30186)
+++ compile.c	(revision 30187)
@@ -418,6 +418,30 @@
     return COMPILE_OK;
 }
 
+static int
+validate_label(st_data_t name, st_data_t label, st_data_t arg)
+{
+    rb_iseq_t *iseq = (rb_iseq_t *)arg;
+    LABEL *lobj = (LABEL *)label;
+    if (!lobj->link.next) {
+	do {
+	    int ret;
+	    COMPILE_ERROR((ruby_sourcefile, lobj->position,
+			   "%s: undefined label", rb_id2name((ID)name)));
+	} while (0);
+    }
+    return ST_CONTINUE;
+}
+
+static void
+validate_labels(rb_iseq_t *iseq, st_table *labels_table)
+{
+    st_foreach(labels_table, validate_label, (st_data_t)iseq);
+    if (!NIL_P(iseq->compile_data->err_info)) {
+	rb_exc_raise(iseq->compile_data->err_info);
+    }
+}
+
 VALUE
 rb_iseq_compile_node(VALUE self, NODE *node)
 {
@@ -503,6 +527,11 @@
 	ADD_INSN(ret, iseq->compile_data->last_line, leave);
     }
 
+#if SUPPORT_JOKE
+    if (iseq->compile_data->labels_table) {
+	validate_labels(iseq, iseq->compile_data->labels_table);
+    }
+#endif
     return iseq_setup(iseq, ret);
 }
 
@@ -4043,27 +4072,36 @@
 	{
 	    ID goto_id;
 	    ID label_id;
-	    VALUE label;
-	    VALUE label_sym;
 
 	    CONST_ID(goto_id, "__goto__");
 	    CONST_ID(label_id, "__label__");
 
 	    if (nd_type(node) == NODE_FCALL &&
 		(mid == goto_id || mid == label_id)) {
+		LABEL *label;
+		st_data_t data;
+		st_table *labels_table = iseq->compile_data->labels_table;
+		ID label_name;
+
+		if (!labels_table) {
+		    labels_table = st_init_numtable();
+		    iseq->compile_data->labels_table = labels_table;
+		}
 		if (nd_type(node->nd_args->nd_head) == NODE_LIT &&
 		    SYMBOL_P(node->nd_args->nd_head->nd_lit)) {
 
-		    label_sym = label = node->nd_args->nd_head->nd_lit;
-		    if ((label =
-			 rb_hash_aref(iseq->compile_data,
-				      label_sym)) == Qnil) {
-			rb_hash_aset(iseq->compile_data, label_sym,
-				     label = NEW_LABEL(nd_line(node)));
+		    label_name = SYM2ID(node->nd_args->nd_head->nd_lit);
+		    if (!st_lookup(labels_table, (st_data_t)label_name, &data)) {
+			label = NEW_LABEL(nd_line(node));
+			label->position = nd_line(node);
+			st_insert(labels_table, (st_data_t)label_name, (st_data_t)label);
 		    }
+		    else {
+			label = (LABEL *)data;
+		    }
 		}
 		else {
-		    rb_bug("invalid goto/label format");
+		    COMPILE_ERROR((ERROR_ARGS "invalid goto/label format"));
 		}
 
 
@@ -5351,6 +5389,7 @@
 	    rb_raise(rb_eTypeError, "unexpected object for instruction");
 	}
     }
+    validate_labels(iseq, labels_table);
     st_free_table(labels_table);
     iseq_setup(iseq, anchor);
     return COMPILE_OK;

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]