mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
matz
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@836 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
3f3bcc697e
commit
23dd3051c0
7 changed files with 129 additions and 64 deletions
13
ChangeLog
13
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>
|
Sat Jul 15 01:32:34 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
|
||||||
|
|
||||||
* eval.c (Init_eval): should prohibit `include' and
|
* eval.c (rb_mod_method): implements unbound method.
|
||||||
`module_function' for class Class. The latter was very
|
|
||||||
dangerous.
|
* 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>
|
Fri Jul 14 17:19:59 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
|
||||||
|
|
||||||
|
|
3
ToDo
3
ToDo
|
@ -74,6 +74,9 @@ Standard Libraries
|
||||||
- alternative for interator? => block_given?
|
- alternative for interator? => block_given?
|
||||||
- regex - /p (make obsolete), /m (new)
|
- regex - /p (make obsolete), /m (new)
|
||||||
- consistent /, %, divmod
|
- consistent /, %, divmod
|
||||||
|
- unbound method object
|
||||||
|
- integrate final.rb into the core.
|
||||||
|
* make clone depend on dup
|
||||||
* Enumerable#sort_by for Schwartzian transformation
|
* Enumerable#sort_by for Schwartzian transformation
|
||||||
* String#scanf(?)
|
* String#scanf(?)
|
||||||
* Object#fmt(?)
|
* Object#fmt(?)
|
||||||
|
|
57
eval.c
57
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, "module_eval", rb_mod_module_eval, -1);
|
||||||
rb_define_method(rb_cModule, "class_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_undef_method(rb_cClass, "module_function");
|
||||||
|
|
||||||
rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, 1);
|
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->body = body;
|
||||||
data->oklass = oklass;
|
data->oklass = oklass;
|
||||||
data->oid = oid;
|
data->oid = oid;
|
||||||
if (OBJ_TAINTED(obj) || OBJ_TAINTED(klass)) {
|
OBJ_INFECT(method, klass);
|
||||||
OBJ_TAINT(method);
|
|
||||||
}
|
|
||||||
|
|
||||||
return method;
|
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
|
static VALUE
|
||||||
rb_obj_method(obj, vid)
|
rb_obj_method(obj, vid)
|
||||||
VALUE obj;
|
VALUE obj;
|
||||||
|
@ -6178,13 +6202,11 @@ mcall(argc, argv, method, recv)
|
||||||
Data_Get_Struct(method, struct METHOD, data);
|
Data_Get_Struct(method, struct METHOD, data);
|
||||||
PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
|
PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
|
||||||
PUSH_TAG(PROT_NONE);
|
PUSH_TAG(PROT_NONE);
|
||||||
if (OBJ_TAINTED(recv) || OBJ_TAINTED(method)) {
|
if (OBJ_TAINTED(method)) {
|
||||||
OBJ_TAINT(method);
|
|
||||||
if (ruby_safe_level < 4) ruby_safe_level = 4;
|
if (ruby_safe_level < 4) ruby_safe_level = 4;
|
||||||
}
|
}
|
||||||
if ((state = EXEC_TAG()) == 0) {
|
if ((state = EXEC_TAG()) == 0) {
|
||||||
result = rb_call0(data->klass, recv, data->id,
|
result = rb_call0(data->klass,recv,data->id,argc,argv,data->body,0);
|
||||||
argc, argv, data->body, 0);
|
|
||||||
}
|
}
|
||||||
POP_TAG();
|
POP_TAG();
|
||||||
POP_ITER();
|
POP_ITER();
|
||||||
|
@ -6212,21 +6234,28 @@ umethod_call(argc, argv, method)
|
||||||
VALUE method;
|
VALUE method;
|
||||||
{
|
{
|
||||||
struct METHOD *data;
|
struct METHOD *data;
|
||||||
|
VALUE recv;
|
||||||
|
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
rb_raise(rb_eArgError, "wrong # of arguments");
|
rb_raise(rb_eArgError, "wrong # of arguments");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recv = argv[0];
|
||||||
Data_Get_Struct(method, struct METHOD, data);
|
Data_Get_Struct(method, struct METHOD, data);
|
||||||
if (FL_TEST(CLASS_OF(argv[0]), FL_SINGLETON) &&
|
if (data->oklass != CLASS_OF(recv)) {
|
||||||
st_lookup(RCLASS(CLASS_OF(argv[0]))->m_tbl, data->oid, 0)) {
|
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));
|
rb_raise(rb_eTypeError, "method `%s' overridden", rb_id2name(data->oid));
|
||||||
}
|
}
|
||||||
if (!rb_obj_is_instance_of(argv[0], data->oklass)) {
|
if (!rb_obj_is_instance_of(recv, data->oklass)) {
|
||||||
rb_raise(rb_eTypeError, "first argument must be instance of %s",
|
rb_raise(rb_eTypeError, "first argument must be an instance of %s",
|
||||||
rb_class2name(data->oklass));
|
rb_class2name(data->oklass));
|
||||||
}
|
}
|
||||||
return mcall(argc-1, argv+1, method, argv[0]);
|
}
|
||||||
|
return mcall(argc-1, argv+1, method, recv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
@ -6362,6 +6391,7 @@ Init_Proc()
|
||||||
rb_define_method(rb_cMethod, "inspect", method_inspect, 0);
|
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_s", method_inspect, 0);
|
||||||
rb_define_method(rb_cMethod, "to_proc", method_proc, 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_define_method(rb_mKernel, "method", rb_obj_method, 1);
|
||||||
|
|
||||||
rb_cUnboundMethod = rb_define_class("UnboundMethod", rb_cMethod);
|
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, "[]", umethod_call, -1);
|
||||||
rb_define_method(rb_cUnboundMethod, "to_proc", umethod_proc, 0);
|
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_cModule, "instance_method", rb_mod_method, 1);
|
||||||
|
rb_define_method(rb_cMethod, "unbound", umethod_unbound, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE rb_eThreadError;
|
static VALUE rb_eThreadError;
|
||||||
|
|
68
gc.c
68
gc.c
|
@ -138,6 +138,7 @@ extern int ruby_in_compile;
|
||||||
static int dont_gc;
|
static int dont_gc;
|
||||||
static int during_gc;
|
static int during_gc;
|
||||||
static int need_call_final = 0;
|
static int need_call_final = 0;
|
||||||
|
static st_table *finalizer_table = 0;
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
gc_enable()
|
gc_enable()
|
||||||
|
@ -931,6 +932,9 @@ rb_gc()
|
||||||
rb_gc_mark(ruby_class);
|
rb_gc_mark(ruby_class);
|
||||||
rb_gc_mark(ruby_scope);
|
rb_gc_mark(ruby_scope);
|
||||||
rb_gc_mark(ruby_dyna_vars);
|
rb_gc_mark(ruby_dyna_vars);
|
||||||
|
if (finalizer_table) {
|
||||||
|
rb_mark_tbl(finalizer_table);
|
||||||
|
}
|
||||||
|
|
||||||
FLUSH_REGISTER_WINDOWS;
|
FLUSH_REGISTER_WINDOWS;
|
||||||
/* This assumes that all registers are saved into the jmp_buf */
|
/* This assumes that all registers are saved into the jmp_buf */
|
||||||
|
@ -1076,6 +1080,7 @@ static VALUE
|
||||||
add_final(os, proc)
|
add_final(os, proc)
|
||||||
VALUE os, proc;
|
VALUE os, proc;
|
||||||
{
|
{
|
||||||
|
rb_warn("ObjectSpace::add_finalizer is deprecated; use define_finalizer");
|
||||||
if (!rb_obj_is_kind_of(proc, rb_cProc)) {
|
if (!rb_obj_is_kind_of(proc, rb_cProc)) {
|
||||||
rb_raise(rb_eArgError, "wrong type argument %s (Proc required)",
|
rb_raise(rb_eArgError, "wrong type argument %s (Proc required)",
|
||||||
rb_class2name(CLASS_OF(proc)));
|
rb_class2name(CLASS_OF(proc)));
|
||||||
|
@ -1088,6 +1093,7 @@ static VALUE
|
||||||
rm_final(os, proc)
|
rm_final(os, proc)
|
||||||
VALUE os, proc;
|
VALUE os, proc;
|
||||||
{
|
{
|
||||||
|
rb_warn("ObjectSpace::remove_finalizer is deprecated; use undefine_finalizer");
|
||||||
rb_ary_delete(finalizers, proc);
|
rb_ary_delete(finalizers, proc);
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
@ -1095,6 +1101,7 @@ rm_final(os, proc)
|
||||||
static VALUE
|
static VALUE
|
||||||
finals()
|
finals()
|
||||||
{
|
{
|
||||||
|
rb_warn("ObjectSpace::finals is deprecated");
|
||||||
return finalizers;
|
return finalizers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1102,11 +1109,55 @@ static VALUE
|
||||||
call_final(os, obj)
|
call_final(os, obj)
|
||||||
VALUE os, obj;
|
VALUE os, obj;
|
||||||
{
|
{
|
||||||
|
rb_warn("ObjectSpace::call_final is deprecated; use define_finalizer");
|
||||||
need_call_final = 1;
|
need_call_final = 1;
|
||||||
FL_SET(obj, FL_FINALIZE);
|
FL_SET(obj, FL_FINALIZE);
|
||||||
return obj;
|
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
|
static VALUE
|
||||||
run_single_final(args)
|
run_single_final(args)
|
||||||
VALUE *args;
|
VALUE *args;
|
||||||
|
@ -1120,14 +1171,21 @@ run_final(obj)
|
||||||
VALUE obj;
|
VALUE obj;
|
||||||
{
|
{
|
||||||
int i, status;
|
int i, status;
|
||||||
VALUE args[2];
|
VALUE id, args[2], table;
|
||||||
|
|
||||||
obj = rb_obj_id(obj); /* make obj into id */
|
id = rb_obj_id(obj); /* make obj into id */
|
||||||
args[1] = rb_ary_new3(1, obj);
|
args[1] = rb_ary_new3(1, id);
|
||||||
for (i=0; i<RARRAY(finalizers)->len; i++) {
|
for (i=0; i<RARRAY(finalizers)->len; i++) {
|
||||||
args[0] = RARRAY(finalizers)->ptr[i];
|
args[0] = RARRAY(finalizers)->ptr[i];
|
||||||
rb_protect(run_single_final, (VALUE)args, &status);
|
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
|
void
|
||||||
|
@ -1204,6 +1262,10 @@ Init_GC()
|
||||||
rb_define_module_function(rb_mObSpace, "remove_finalizer", rm_final, 1);
|
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, "finalizers", finals, 0);
|
||||||
rb_define_module_function(rb_mObSpace, "call_finalizer", call_final, 1);
|
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_define_module_function(rb_mObSpace, "_id2ref", id2ref, 1);
|
||||||
|
|
||||||
rb_gc_register_address(&rb_mObSpace);
|
rb_gc_register_address(&rb_mObSpace);
|
||||||
|
|
39
lib/final.rb
39
lib/final.rb
|
@ -1,41 +1,4 @@
|
||||||
#
|
|
||||||
# $Id$
|
# $Id$
|
||||||
# Copyright (C) 1998 Yukihiro Matsumoto. All rights reserved.
|
# Copyright (C) 1998 Yukihiro Matsumoto. All rights reserved.
|
||||||
|
|
||||||
# The ObjectSpace extension:
|
# final.rb is integrated into ObjectSpace; no longer needed.
|
||||||
#
|
|
||||||
# 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
|
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
# o file mode of the temporary files are 0600.
|
# o file mode of the temporary files are 0600.
|
||||||
|
|
||||||
require 'delegate'
|
require 'delegate'
|
||||||
require 'final'
|
|
||||||
|
|
||||||
class Tempfile < SimpleDelegator
|
class Tempfile < SimpleDelegator
|
||||||
Max_try = 10
|
Max_try = 10
|
||||||
|
|
4
st.c
4
st.c
|
@ -546,14 +546,14 @@ strhash(string)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
numcmp(x, y)
|
numcmp(x, y)
|
||||||
int x, y;
|
long x, y;
|
||||||
{
|
{
|
||||||
return x != y;
|
return x != y;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
numhash(n)
|
numhash(n)
|
||||||
int n;
|
long n;
|
||||||
{
|
{
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue