Vladimir Sizikov wrote:
> I've written a small quick starting guide here:
> http://blog.emptyway.com/2008/04/06/the-rubyspecs-quick-starting-guide/

 Thanks,

vgs% bin/mspec -t ruby spec/ruby/1.8/core/kernel
ruby 1.8.6 (2008-04-06 patchlevel 5000) [i686-linux]
.......................................................................................................................................................................................................................................................................................................................

Finished in 0.190939 seconds

101 files, 311 examples, 2658 expectations, 0 failures, 0 errors
vgs%


 Please verify it

Guy Decoux




Index: intern.h
===================================================================
--- intern.h	(revision 15910)
+++ intern.h	(working copy)
@@ -184,6 +184,8 @@
 void rb_obj_call_init _((VALUE, int, VALUE*));
 VALUE rb_class_new_instance _((int, VALUE*, VALUE));
 VALUE rb_block_proc _((void));
+VALUE rb_block_dup _((VALUE, VALUE, VALUE));
+VALUE rb_method_dup _((VALUE, VALUE, VALUE));
 VALUE rb_f_lambda _((void));
 VALUE rb_proc_new _((VALUE (*)(ANYARGS/* VALUE yieldarg[, VALUE
procarg] */), VALUE));
 VALUE rb_protect _((VALUE (*)(VALUE), VALUE, int*));
Index: class.c
===================================================================
--- class.c	(revision 15910)
+++ class.c	(working copy)
@@ -51,6 +51,7 @@
 struct clone_method_data {
     st_table *tbl;
     VALUE klass;
+    VALUE cref;
 };

 static int
@@ -59,18 +60,75 @@
     NODE *body;
     struct clone_method_data *data;
 {
-    NODE *fbody = body->nd_body;
+    NODE *node = body->nd_body;
+    if (node && data->cref) {
+	switch(nd_type(node)) {
+	case NODE_SCOPE:
+	    if (node->nd_rval) {
+		NODE *tmp = NEW_NODE(nd_type(node->u2.node), data->cref,
+				     node->u2.node->u2.node, node->u2.node->u3.node);
+		node = NEW_NODE(nd_type(node), node->u1.node, tmp, node->u3.node);
+	    }
+	    break;
+
+	case NODE_BMETHOD:
+	{
+	    VALUE body = rb_block_dup(node->nd_cval, data->klass, data->cref);
+	    node = NEW_BMETHOD(body);
+	    break;
+	}
+
+	case NODE_DMETHOD:
+	{
+	    VALUE body = rb_method_dup(node->nd_cval, data->klass, data->cref);
+	    node = NEW_DMETHOD(body);
+	    break;
+	}

-    if (fbody && nd_type(fbody) == NODE_SCOPE) {
-	VALUE cref = data->klass ?
-	    (VALUE)NEW_NODE(NODE_CREF,data->klass,0,fbody->nd_rval) :
-	    fbody->nd_rval;
-	fbody = NEW_NODE(NODE_SCOPE, fbody->nd_tbl, cref, fbody->nd_next);
+	}
     }
-    st_insert(data->tbl, mid, (st_data_t)NEW_METHOD(fbody, body->nd_noex));
+    st_insert(data->tbl, mid, (st_data_t)NEW_METHOD(node, body->nd_noex));
     return ST_CONTINUE;
 }

+static VALUE
+singleton_class_clone_int(obj, cref)
+    VALUE obj, cref;
+{
+    VALUE klass = RBASIC(obj)->klass;
+
+    if (!FL_TEST(klass, FL_SINGLETON))
+	return klass;
+    else {
+	struct clone_method_data data;
+	/* copy singleton(unnamed) class */
+	NEWOBJ(clone, struct RClass);
+	OBJSETUP(clone, 0, RBASIC(klass)->flags);
+
+	if (BUILTIN_TYPE(obj) == T_CLASS) {
+	    RBASIC(clone)->klass = (VALUE)clone;
+	}
+	else {
+	    RBASIC(clone)->klass = rb_singleton_class_clone(klass);
+	}
+
+	clone->super = RCLASS(klass)->super;
+	clone->iv_tbl = 0;
+	clone->m_tbl = 0;
+	if (RCLASS(klass)->iv_tbl) {
+	    clone->iv_tbl = st_copy(RCLASS(klass)->iv_tbl);
+	}
+	clone->m_tbl = st_init_numtable();
+	data.tbl = clone->m_tbl;
+	data.klass = (VALUE)clone;
+	data.cref = cref;
+	st_foreach(RCLASS(klass)->m_tbl, clone_method, (st_data_t)&data);
+	rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
+	FL_SET(clone, FL_SINGLETON);
+	return (VALUE)clone;
+    }
+}
+
 /* :nodoc: */
 VALUE
 rb_mod_init_copy(clone, orig)
@@ -78,8 +136,7 @@
 {
     rb_obj_init_copy(clone, orig);
     if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
-	RBASIC(clone)->klass = RBASIC(orig)->klass;
-	RBASIC(clone)->klass = rb_singleton_class_clone(clone);
+	RBASIC(clone)->klass = singleton_class_clone_int(orig, clone);
     }
     RCLASS(clone)->super = RCLASS(orig)->super;
     if (RCLASS(orig)->iv_tbl) {
@@ -94,9 +151,10 @@
     if (RCLASS(orig)->m_tbl) {
 	struct clone_method_data data;

-	data.tbl = RCLASS(clone)->m_tbl = st_init_numtable();
-	data.klass = (VALUE)clone;
-
+ 	RCLASS(clone)->m_tbl = st_init_numtable();
+	data.tbl = RCLASS(clone)->m_tbl;
+	data.klass = clone;
+	data.cref = clone;
 	st_foreach(RCLASS(orig)->m_tbl, clone_method, (st_data_t)&data);
     }

@@ -121,48 +179,7 @@
 rb_singleton_class_clone(obj)
     VALUE obj;
 {
-    VALUE klass = RBASIC(obj)->klass;
-
-    if (!FL_TEST(klass, FL_SINGLETON))
-	return klass;
-    else {
-	/* copy singleton(unnamed) class */
-	NEWOBJ(clone, struct RClass);
-	OBJSETUP(clone, 0, RBASIC(klass)->flags);
-
-	if (BUILTIN_TYPE(obj) == T_CLASS) {
-	    RBASIC(clone)->klass = (VALUE)clone;
-	}
-	else {
-	    RBASIC(clone)->klass = rb_singleton_class_clone(klass);
-	}
-
-	clone->super = RCLASS(klass)->super;
-	clone->iv_tbl = 0;
-	clone->m_tbl = 0;
-	if (RCLASS(klass)->iv_tbl) {
-	    clone->iv_tbl = st_copy(RCLASS(klass)->iv_tbl);
-	}
-	{
-	    struct clone_method_data data;
-
-	    data.tbl = clone->m_tbl = st_init_numtable();
-	    switch (TYPE(obj)) {
-	      case T_CLASS:
-	      case T_MODULE:
-		data.klass = obj;
-		break;
-	      default:
-		data.klass = 0;
-		break;
-	    }
-
-	    st_foreach(RCLASS(klass)->m_tbl, clone_method, (st_data_t)&data);
-	}
-	rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
-	FL_SET(clone, FL_SINGLETON);
-	return (VALUE)clone;
-    }
+    return singleton_class_clone_int(obj, 0);
 }

 void
Index: eval.c
===================================================================
--- eval.c	(revision 15910)
+++ eval.c	(working copy)
@@ -8358,6 +8358,19 @@
     return bind;
 }

+VALUE
+rb_block_dup(self, klass, cref)
+    VALUE self, klass, cref;
+{
+    struct BLOCK *block;
+    VALUE obj = proc_dup(self);
+    Data_Get_Struct(obj, struct BLOCK, block);
+    block->klass = klass;
+    block->cref = NEW_NODE(nd_type(block->cref), cref,
block->cref->u2.node,
+			   block->cref->u3.node);
+    return obj;
+}
+
 /*
  *  call-seq:
  *     binding -> a_binding
@@ -9204,6 +9217,29 @@
     return clone;
 }

+VALUE
+rb_method_dup(self, klass, cref)
+    VALUE self;
+    VALUE klass;
+    VALUE cref;
+{
+    VALUE clone;
+    struct METHOD *orig, *data;
+
+    Data_Get_Struct(self, struct METHOD, orig);
+    clone = Data_Make_Struct(CLASS_OF(self),struct METHOD, bm_mark,
free, data);
+    *data = *orig;
+    data->rklass = klass;
+    if (data->body->nd_rval) {
+	NODE *tmp = NEW_NODE(nd_type(data->body->u2.node), cref,
+			     data->body->u2.node->u2.node,
+			     data->body->u2.node->u3.node);
+	data->body = NEW_NODE(nd_type(data->body), data->body->u1.node, tmp,
+			      data->body->u3.node);
+    }
+    return clone;
+}
+
 /*
  *  call-seq:
  *     meth.call(args, ...)    => obj