[#18121] [Ruby 1.8.7 - Bug #405] (Open) ssl.rb:31: [BUG] Bus Error — Anonymous <redmine@...>

Issue #405 has been reported by Anonymous.

14 messages 2008/08/04

[#18130] Re: New array methods cycle, choice, shuffle (plus bug in cycle) — Brian Candler <B.Candler@...>

> Seriously though... Array.first is a noun.

10 messages 2008/08/05

[#18319] NEW Command: absolute_path() -- — "C.E. Thornton" <admin@...>

Core,

14 messages 2008/08/16
[#18321] Re: NEW Command: absolute_path() -- — Yukihiro Matsumoto <matz@...> 2008/08/18

Hi,

[#18381] [Bug #496] DRb.start_service(nil) is very slow — Hongli Lai <redmine@...>

Bug #496: DRb.start_service(nil) is very slow

11 messages 2008/08/25

[ruby-core:18349] [Feature:1.9] autoload with a block

From: Nobuyoshi Nakada <nobu@...>
Date: 2008-08-20 02:13:17 UTC
List: ruby-core #18349
Hi,

At Mon, 18 Aug 2008 10:35:01 +0900,
Nobuyoshi Nakada wrote in [ruby-talk:311603]:
> At Fri, 15 Aug 2008 15:57:21 +0900,
> David Masover wrote in [ruby-talk:311365]:
> > autoload :Foo do
> >   require 'foo'
> >   Foo.autoload :Bar ...
> > end
> > 
> > In that simplest form, it would at least centralize all my loading stuff in 
> > one place. In a more meta form, I could run through some search paths I'm 
> > likely to use (in my own app, for instance), and generate an autoload scheme 
> > based on that.
> 
> I don't think it makes things simpler, but it sounds
> interesting.  You can file it in the ITS, if you want.
> <http://redmine.ruby-lang.org/projects/ruby/issues?set_filter=1&tracker_id=2>

Although the OP doesn't seem to intend to request this feature,
I move it to ruby-core since it feels interesting.


Index: load.c
===================================================================
--- load.c	(revision 18653)
+++ load.c	(working copy)
@@ -618,10 +618,29 @@ ruby_init_ext(const char *name, void (*i
 
 static VALUE
-rb_mod_autoload(VALUE mod, VALUE sym, VALUE file)
+rb_mod_autoload(int argc, VALUE *argv, VALUE mod)
 {
-    ID id = rb_to_id(sym);
-
-    Check_SafeStr(file);
-    rb_autoload(mod, id, RSTRING_PTR(file));
+    extern VALUE rb_autoload_proc(VALUE, ID, VALUE, VALUE);
+    ID id;
+    VALUE block = rb_block_given_p() ? rb_block_proc() : Qnil;
+    VALUE arg = Qnil;
+
+    switch (argc) {
+      case 2:
+	arg = argv[1];
+	break;
+      case 1:
+	if (!NIL_P(block)) break;
+      default:
+	rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
+    }
+    id = rb_to_id(argv[0]);
+    if (NIL_P(block)) {
+	VALUE file = argv[1];
+	Check_SafeStr(file);
+	rb_autoload(mod, id, RSTRING_PTR(file));
+    }
+    else {
+	rb_autoload_proc(mod, id, block, arg);
+    }
     return Qnil;
 }
@@ -649,5 +668,5 @@ rb_mod_autoload_p(VALUE mod, VALUE sym)
 
 static VALUE
-rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
+rb_f_autoload(int argc, VALUE *argv, VALUE obj)
 {
     VALUE klass = rb_vm_cbase();
@@ -655,5 +674,5 @@ rb_f_autoload(VALUE obj, VALUE sym, VALU
 	rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
     }
-    return rb_mod_autoload(klass, sym, file);
+    return rb_mod_autoload(argc, argv, klass);
 }
 
@@ -693,7 +712,7 @@ Init_load()
     rb_define_global_function("load", rb_f_load, -1);
     rb_define_global_function("require", rb_f_require, 1);
-    rb_define_method(rb_cModule, "autoload", rb_mod_autoload, 2);
+    rb_define_method(rb_cModule, "autoload", rb_mod_autoload, -1);
     rb_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, 1);
-    rb_define_global_function("autoload", rb_f_autoload, 2);
+    rb_define_global_function("autoload", rb_f_autoload, -1);
     rb_define_global_function("autoload?", rb_f_autoload_p, 1);
 
Index: variable.c
===================================================================
--- variable.c	(revision 18653)
+++ variable.c	(working copy)
@@ -1322,16 +1322,12 @@ check_autoload_table(VALUE av)
 }
 
-void
-rb_autoload(VALUE mod, ID id, const char *file)
+typedef VALUE rb_autoload_func(VALUE, ID, VALUE, VALUE);
+
+static void
+autoload_callback(VALUE mod, ID id, rb_autoload_func *func, VALUE arg1, VALUE arg2)
 {
-    VALUE av, fn;
+    VALUE av;
     struct st_table *tbl;
-
-    if (!rb_is_const_id(id)) {
-	rb_raise(rb_eNameError, "autoload must be constant name: %s", rb_id2name(id));
-    }
-    if (!file || !*file) {
-	rb_raise(rb_eArgError, "empty file name");
-    }
+    NODE *n;
 
     if ((tbl = RCLASS_IV_TBL(mod)) && st_lookup(tbl, id, &av) && av != Qundef)
@@ -1348,8 +1344,61 @@ rb_autoload(VALUE mod, ID id, const char
 	DATA_PTR(av) = tbl = st_init_numtable();
     }
+
+    n = rb_node_newnode(NODE_MEMO, (VALUE)func, arg1, arg2);
+    st_insert(tbl, id, (st_data_t)n);
+}
+
+static VALUE
+autoload_load(VALUE klass, ID id, VALUE file, VALUE safe)
+{
+    return rb_require_safe(file, (int)safe);
+}
+
+static void
+check_autoload_id(ID id)
+{
+    if (!rb_is_const_id(id)) {
+	rb_raise(rb_eNameError, "autoload must be constant name: %s", rb_id2name(id));
+    }
+}
+
+void
+rb_autoload(VALUE mod, ID id, const char *file)
+{
+    VALUE fn;
+
+    check_autoload_id(id);
+    if (!file || !*file) {
+	rb_raise(rb_eArgError, "empty file name");
+    }
+
     fn = rb_str_new2(file);
     FL_UNSET(fn, FL_TAINT);
     OBJ_FREEZE(fn);
-    st_insert(tbl, id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0));
+
+    autoload_callback(mod, id, autoload_load, fn, (VALUE)rb_safe_level());
+}
+
+void
+rb_autoload_callback(VALUE mod, ID id, rb_autoload_func *func, VALUE arg1, VALUE arg2)
+{
+    check_autoload_id(id);
+    autoload_callback(mod, id, func, arg1, arg2);
+}
+
+static VALUE
+autoload_proc_call(VALUE mod, ID id, VALUE proc, VALUE arg)
+{
+    VALUE args[3];
+    args[0] = mod;
+    args[1] = ID2SYM(id);
+    args[2] = arg;
+    return rb_proc_call_with_block(proc, 3, args, Qnil);
+}
+
+void
+rb_autoload_proc(VALUE mod, ID id, VALUE proc, VALUE arg)
+{
+    rb_autoload_callback(mod, id, autoload_proc_call, proc, arg);
 }
 
@@ -1382,25 +1431,34 @@ VALUE
 rb_autoload_load(VALUE klass, ID id)
 {
-    VALUE file;
     NODE *load = autoload_delete(klass, id);
 
-    if (!load || !(file = load->nd_lit)) {
+    if (!load) {
 	return Qfalse;
     }
-    return rb_require_safe(file, load->nd_nth);
+    return load->u1.cfunc(klass, id, load->u2.value, load->u3.value);
 }
 
 static VALUE
-autoload_file(VALUE mod, ID id)
+autoload_p(VALUE mod, ID id)
 {
     VALUE val, file;
     struct st_table *tbl;
-    st_data_t load;
+    st_data_t data;
+    NODE *load;
 
-    if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) ||
-	!(tbl = check_autoload_table(val)) || !st_lookup(tbl, id, &load)) {
+    if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &data) ||
+	!(tbl = check_autoload_table(val = (VALUE)data)) ||
+	!st_lookup(tbl, id, &data)) {
 	return Qnil;
     }
-    file = ((NODE *)load)->nd_lit;
+    load = (NODE *)data;
+    if (load->u1.cfunc == autoload_proc_call) {
+	/* rb_obj_is_proc() */
+	return load->u2.value;
+    }
+    if (load->u1.cfunc != autoload_load) {
+	return Qtrue;
+    }
+    file = load->u2.value;
     Check_Type(file, T_STRING);
     if (!RSTRING_PTR(file) || !*RSTRING_PTR(file)) {
@@ -1433,5 +1491,5 @@ rb_autoload_p(VALUE mod, ID id)
 	return Qnil;
     }
-    return autoload_file(mod, id);
+    return autoload_p(mod, id);
 }
 
@@ -1630,5 +1688,5 @@ rb_const_defined_0(VALUE klass, ID id, i
     while (tmp) {
 	if (RCLASS_IV_TBL(tmp) && st_lookup(RCLASS_IV_TBL(tmp), id, &value)) {
-	    if (value == Qundef && NIL_P(autoload_file(klass, id)))
+	    if (value == Qundef && NIL_P(autoload_p(klass, id)))
 		return Qfalse;
 	    return Qtrue;


-- 
Nobu Nakada

In This Thread

Prev Next