From 23dd3051c06c781b3905c993fd8fc1b3ccff6b81 Mon Sep 17 00:00:00 2001 From: matz Date: Sat, 15 Jul 2000 13:37:03 +0000 Subject: [PATCH] matz git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@836 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 13 +++++++--- ToDo | 3 +++ eval.c | 65 +++++++++++++++++++++++++++++++++------------- gc.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++--- lib/final.rb | 39 +--------------------------- lib/tempfile.rb | 1 - st.c | 4 +-- 7 files changed, 129 insertions(+), 64 deletions(-) diff --git a/ChangeLog b/ChangeLog index f84351e965..47824482b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,15 @@ +Sat Jul 15 21:59:58 2000 Yukihiro Matsumoto + + * gc.c (define_final): integrate final.rb features into the + interpreter. define_finalizer and undefine_finalizer was + added to ObjectSpace. + Sat Jul 15 01:32:34 2000 Yukihiro Matsumoto - * eval.c (Init_eval): should prohibit `include' and - `module_function' for class Class. The latter was very - dangerous. + * eval.c (rb_mod_method): implements unbound method. + + * eval.c (Init_eval): should prohibit `module_function' for class + Class. Fri Jul 14 17:19:59 2000 WATANABE Hirofumi diff --git a/ToDo b/ToDo index 05cec797e2..b4918d91b7 100644 --- a/ToDo +++ b/ToDo @@ -74,6 +74,9 @@ Standard Libraries - alternative for interator? => block_given? - regex - /p (make obsolete), /m (new) - consistent /, %, divmod +- unbound method object +- integrate final.rb into the core. +* make clone depend on dup * Enumerable#sort_by for Schwartzian transformation * String#scanf(?) * Object#fmt(?) diff --git a/eval.c b/eval.c index c399cc7fd2..dda4ef33bc 100644 --- a/eval.c +++ b/eval.c @@ -5558,7 +5558,6 @@ Init_eval() rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1); rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1); - rb_undef_method(rb_cClass, "include"); rb_undef_method(rb_cClass, "module_function"); rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, 1); @@ -6126,13 +6125,38 @@ mnew(klass, obj, id, mklass) data->body = body; data->oklass = oklass; data->oid = oid; - if (OBJ_TAINTED(obj) || OBJ_TAINTED(klass)) { - OBJ_TAINT(method); - } + OBJ_INFECT(method, klass); return method; } +static VALUE +method_unbound(obj) + VALUE obj; +{ + VALUE method; + struct METHOD *orig, *data; + + Data_Get_Struct(obj, struct METHOD, orig); + method = Data_Make_Struct(rb_cUnboundMethod, struct METHOD, bm_mark, free, data); + data->klass = orig->klass; + data->recv = 0; + data->id = orig->id; + data->body = orig->body; + data->oklass = orig->oklass; + data->oid = orig->oid; + OBJ_INFECT(method, orig->klass); + + return method; +} + +static VALUE +umethod_unbound(obj) + VALUE obj; +{ + return obj; +} + static VALUE rb_obj_method(obj, vid) VALUE obj; @@ -6178,13 +6202,11 @@ mcall(argc, argv, method, recv) Data_Get_Struct(method, struct METHOD, data); PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT); PUSH_TAG(PROT_NONE); - if (OBJ_TAINTED(recv) || OBJ_TAINTED(method)) { - OBJ_TAINT(method); + if (OBJ_TAINTED(method)) { if (ruby_safe_level < 4) ruby_safe_level = 4; } if ((state = EXEC_TAG()) == 0) { - result = rb_call0(data->klass, recv, data->id, - argc, argv, data->body, 0); + result = rb_call0(data->klass,recv,data->id,argc,argv,data->body,0); } POP_TAG(); POP_ITER(); @@ -6212,21 +6234,28 @@ umethod_call(argc, argv, method) VALUE method; { struct METHOD *data; + VALUE recv; if (argc < 1) { rb_raise(rb_eArgError, "wrong # of arguments"); } - + + recv = argv[0]; Data_Get_Struct(method, struct METHOD, data); - if (FL_TEST(CLASS_OF(argv[0]), FL_SINGLETON) && - st_lookup(RCLASS(CLASS_OF(argv[0]))->m_tbl, data->oid, 0)) { - rb_raise(rb_eTypeError, "method `%s' overridden", rb_id2name(data->oid)); + if (data->oklass != CLASS_OF(recv)) { + if (FL_TEST(data->oklass, FL_SINGLETON)) { + rb_raise(rb_eTypeError, "singleton method called for a different object"); + } + if (FL_TEST(CLASS_OF(recv), FL_SINGLETON) && + st_lookup(RCLASS(CLASS_OF(recv))->m_tbl, data->oid, 0)) { + rb_raise(rb_eTypeError, "method `%s' overridden", rb_id2name(data->oid)); + } + if (!rb_obj_is_instance_of(recv, data->oklass)) { + rb_raise(rb_eTypeError, "first argument must be an instance of %s", + rb_class2name(data->oklass)); + } } - if (!rb_obj_is_instance_of(argv[0], data->oklass)) { - rb_raise(rb_eTypeError, "first argument must be instance of %s", - rb_class2name(data->oklass)); - } - return mcall(argc-1, argv+1, method, argv[0]); + return mcall(argc-1, argv+1, method, recv); } static VALUE @@ -6362,6 +6391,7 @@ Init_Proc() rb_define_method(rb_cMethod, "inspect", method_inspect, 0); rb_define_method(rb_cMethod, "to_s", method_inspect, 0); rb_define_method(rb_cMethod, "to_proc", method_proc, 0); + rb_define_method(rb_cMethod, "unbound", method_unbound, 0); rb_define_method(rb_mKernel, "method", rb_obj_method, 1); rb_cUnboundMethod = rb_define_class("UnboundMethod", rb_cMethod); @@ -6369,6 +6399,7 @@ Init_Proc() rb_define_method(rb_cUnboundMethod, "[]", umethod_call, -1); rb_define_method(rb_cUnboundMethod, "to_proc", umethod_proc, 0); rb_define_method(rb_cModule, "instance_method", rb_mod_method, 1); + rb_define_method(rb_cMethod, "unbound", umethod_unbound, 0); } static VALUE rb_eThreadError; diff --git a/gc.c b/gc.c index 5bbd48bf8e..6a31ee0a1c 100644 --- a/gc.c +++ b/gc.c @@ -138,6 +138,7 @@ extern int ruby_in_compile; static int dont_gc; static int during_gc; static int need_call_final = 0; +static st_table *finalizer_table = 0; static VALUE gc_enable() @@ -931,6 +932,9 @@ rb_gc() rb_gc_mark(ruby_class); rb_gc_mark(ruby_scope); rb_gc_mark(ruby_dyna_vars); + if (finalizer_table) { + rb_mark_tbl(finalizer_table); + } FLUSH_REGISTER_WINDOWS; /* This assumes that all registers are saved into the jmp_buf */ @@ -1076,6 +1080,7 @@ static VALUE add_final(os, proc) VALUE os, proc; { + rb_warn("ObjectSpace::add_finalizer is deprecated; use define_finalizer"); if (!rb_obj_is_kind_of(proc, rb_cProc)) { rb_raise(rb_eArgError, "wrong type argument %s (Proc required)", rb_class2name(CLASS_OF(proc))); @@ -1088,6 +1093,7 @@ static VALUE rm_final(os, proc) VALUE os, proc; { + rb_warn("ObjectSpace::remove_finalizer is deprecated; use undefine_finalizer"); rb_ary_delete(finalizers, proc); return proc; } @@ -1095,6 +1101,7 @@ rm_final(os, proc) static VALUE finals() { + rb_warn("ObjectSpace::finals is deprecated"); return finalizers; } @@ -1102,11 +1109,55 @@ static VALUE call_final(os, obj) VALUE os, obj; { + rb_warn("ObjectSpace::call_final is deprecated; use define_finalizer"); need_call_final = 1; FL_SET(obj, FL_FINALIZE); return obj; } +static VALUE +undefine_final(os, obj) + VALUE os, obj; +{ + VALUE table; + + if (finalizer_table) { + st_delete(finalizer_table, &obj, 0); + } + return obj; +} + +static VALUE +define_final(argc, argv, os) + int argc; + VALUE *argv; + VALUE os; +{ + VALUE obj, proc, table; + + rb_scan_args(argc, argv, "11", &obj, &proc); + if (argc == 1) { + proc = rb_f_lambda(); + } + else if (!rb_obj_is_kind_of(proc, rb_cProc)) { + rb_raise(rb_eArgError, "wrong type argument %s (Proc required)", + rb_class2name(CLASS_OF(proc))); + } + need_call_final = 1; + FL_SET(obj, FL_FINALIZE); + + if (!finalizer_table) { + finalizer_table = st_init_numtable(); + } + if (st_lookup(finalizer_table, obj, &table)) { + rb_ary_push(table, proc); + } + else { + st_add_direct(finalizer_table, obj, rb_ary_new3(1, proc)); + } + return proc; +} + static VALUE run_single_final(args) VALUE *args; @@ -1120,14 +1171,21 @@ run_final(obj) VALUE obj; { int i, status; - VALUE args[2]; + VALUE id, args[2], table; - obj = rb_obj_id(obj); /* make obj into id */ - args[1] = rb_ary_new3(1, obj); + id = rb_obj_id(obj); /* make obj into id */ + args[1] = rb_ary_new3(1, id); for (i=0; ilen; i++) { args[0] = RARRAY(finalizers)->ptr[i]; rb_protect(run_single_final, (VALUE)args, &status); } + if (finalizer_table && st_lookup(finalizer_table, obj, &table)) { + st_delete(finalizer_table, &obj, 0); + for (i=0; ilen; i++) { + args[0] = RARRAY(table)->ptr[i]; + rb_protect(run_single_final, (VALUE)args, &status); + } + } } void @@ -1204,6 +1262,10 @@ Init_GC() rb_define_module_function(rb_mObSpace, "remove_finalizer", rm_final, 1); rb_define_module_function(rb_mObSpace, "finalizers", finals, 0); rb_define_module_function(rb_mObSpace, "call_finalizer", call_final, 1); + + rb_define_module_function(rb_mObSpace, "define_finalizer", define_final, -1); + rb_define_module_function(rb_mObSpace, "undefine_finalizer", undefine_final, 1); + rb_define_module_function(rb_mObSpace, "_id2ref", id2ref, 1); rb_gc_register_address(&rb_mObSpace); diff --git a/lib/final.rb b/lib/final.rb index cdffd941e7..9d81238823 100644 --- a/lib/final.rb +++ b/lib/final.rb @@ -1,41 +1,4 @@ -# # $Id$ # Copyright (C) 1998 Yukihiro Matsumoto. All rights reserved. -# The ObjectSpace extension: -# -# ObjectSpace.define_finalizer(obj, proc=lambda()) -# -# Defines the finalizer for the specified object. -# -# ObjectSpace.undefine_finalizer(obj) -# -# Removes the finalizers for the object. If multiple finalizers are -# defined for the object, all finalizers will be removed. -# - -module ObjectSpace - Finalizers = {} - def define_finalizer(obj, proc=lambda()) - ObjectSpace.call_finalizer(obj) - if assoc = Finalizers[obj.id] - assoc.push(proc) - else - Finalizers[obj.id] = [proc] - end - end - def undefine_finalizer(obj) - Finalizers.delete(obj.id) - end - module_function :define_finalizer, :undefine_finalizer - - Generic_Finalizer = proc {|id| - if Finalizers.key? id - for proc in Finalizers[id] - proc.call(id) - end - Finalizers.delete(id) - end - } - add_finalizer Generic_Finalizer -end +# final.rb is integrated into ObjectSpace; no longer needed. diff --git a/lib/tempfile.rb b/lib/tempfile.rb index 0e4c99e5ff..10f05a3b2b 100644 --- a/lib/tempfile.rb +++ b/lib/tempfile.rb @@ -10,7 +10,6 @@ # o file mode of the temporary files are 0600. require 'delegate' -require 'final' class Tempfile < SimpleDelegator Max_try = 10 diff --git a/st.c b/st.c index e7bd0ecf52..f14c69f271 100644 --- a/st.c +++ b/st.c @@ -546,14 +546,14 @@ strhash(string) static int numcmp(x, y) - int x, y; + long x, y; { return x != y; } static int numhash(n) - int n; + long n; { return n; }