1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@836 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2000-07-15 13:37:03 +00:00
parent 3f3bcc697e
commit 23dd3051c0
7 changed files with 129 additions and 64 deletions

View file

@ -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>

3
ToDo
View file

@ -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(?)

65
eval.c
View file

@ -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;

68
gc.c
View file

@ -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; 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);

View file

@ -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.

View file

@ -10,7 +10,6 @@
# o file mode of the temporary files are 0600.
require 'delegate'
require 'final'
class Tempfile < SimpleDelegator
Max_try = 10

4
st.c
View file

@ -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;
}