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>
|
||||
|
||||
* 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
3
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(?)
|
||||
|
|
65
eval.c
65
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;
|
||||
|
|
68
gc.c
68
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; 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);
|
||||
|
|
39
lib/final.rb
39
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.
|
||||
|
|
|
@ -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
4
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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue