summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2000-07-15 13:37:03 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2000-07-15 13:37:03 +0000
commit23dd3051c06c781b3905c993fd8fc1b3ccff6b81 (patch)
tree141b338eb698556bb47682ada965c2cd331825bb
parent3f3bcc697e989078e946ac01313d5e36cfaa3d7d (diff)
matz
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@836 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog13
-rw-r--r--ToDo3
-rw-r--r--eval.c65
-rw-r--r--gc.c68
-rw-r--r--lib/final.rb39
-rw-r--r--lib/tempfile.rb1
-rw-r--r--st.c4
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 <matz@netlab.co.jp>
+
+ * 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 <matz@netlab.co.jp>
- * 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 <eban@os.rim.or.jp>
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,14 +6125,39 @@ 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;
VALUE vid;
@@ -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 (!rb_obj_is_instance_of(argv[0], data->oklass)) {
- rb_raise(rb_eTypeError, "first argument must be instance of %s",
- rb_class2name(data->oklass));
+ 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));
+ }
}
- 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,12 +1109,56 @@ 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; i<RARRAY(finalizers)->len; 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; i<RARRAY(table)->len; 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;
}