mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* eval.c (method_hash): new method. [ruby-talk:93968]
* eval.c (proc_eq): do not compare dyna_vars. * eval.c (proc_hash): new method. * eval.c (rb_yield_0): protect break/return from within orphan (or lambda) Proc object. * parse.y (yylex): should not allow symbol for invalid global variable (e.g. `:$-)`). [ruby-core:02518] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5879 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
e3b15cf111
commit
54a0407425
7 changed files with 125 additions and 13 deletions
16
ChangeLog
16
ChangeLog
|
@ -1,3 +1,14 @@
|
|||
Wed Mar 3 13:10:56 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* eval.c (method_hash): new method. [ruby-talk:93968]
|
||||
|
||||
* eval.c (proc_eq): do not compare dyna_vars.
|
||||
|
||||
* eval.c (proc_hash): new method.
|
||||
|
||||
* eval.c (rb_yield_0): protect break/return from within orphan (or
|
||||
lambda) Proc object.
|
||||
|
||||
Wed Mar 3 09:52:05 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* lib/mkmf.rb ($topdir): use compile_dir only when not installed yet.
|
||||
|
@ -101,6 +112,11 @@ Sat Feb 28 10:31:03 2004 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
|
|||
* lib/erb.rb, test/erb/test_erb.rb: don't forget filename,
|
||||
if both filename and safe_level given. [ruby-dev:23050]
|
||||
|
||||
Sat Feb 28 01:08:40 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* parse.y (yylex): should not allow symbol for invalid global
|
||||
variable (e.g. `:$-)`). [ruby-core:02518]
|
||||
|
||||
Fri Feb 27 20:37:09 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* eval.c (proc_invoke): no orphan block check is needed when pcall
|
||||
|
|
|
@ -115,7 +115,7 @@ can be cast to retrieve the pointer to the struct. The casting macro
|
|||
will be of the form RXXXX for each data type; for instance, RARRAY(obj).
|
||||
See "ruby.h".
|
||||
|
||||
For example, `RSTRING(size)->len' is the way to get the size of the
|
||||
For example, `RSTRING(str)->len' is the way to get the size of the
|
||||
Ruby String object. The allocated region can be accessed by
|
||||
`RSTRING(str)->ptr'. For arrays, use `RARRAY(ary)->len' and
|
||||
`RARRAY(ary)->ptr' respectively.
|
||||
|
|
77
eval.c
77
eval.c
|
@ -993,10 +993,11 @@ static NODE *compile _((VALUE, char*, int));
|
|||
|
||||
static VALUE rb_yield_0 _((VALUE, VALUE, VALUE, int, int));
|
||||
|
||||
#define YIELD_LAMBDA_CALL 1
|
||||
#define YIELD_PUBLIC_DEF 2
|
||||
#define YIELD_FUNC_AVALUE 1
|
||||
#define YIELD_FUNC_SVALUE 2
|
||||
#define YIELD_LAMBDA_CALL 1
|
||||
#define YIELD_BLOCK_ORPHAN 2
|
||||
#define YIELD_PUBLIC_DEF 4
|
||||
#define YIELD_FUNC_AVALUE 1
|
||||
#define YIELD_FUNC_SVALUE 2
|
||||
|
||||
static VALUE rb_call _((VALUE,VALUE,ID,int,const VALUE*,int));
|
||||
static VALUE module_setup _((VALUE,NODE*));
|
||||
|
@ -1257,6 +1258,7 @@ ruby_init()
|
|||
}
|
||||
POP_SCOPE();
|
||||
ruby_scope = top_scope;
|
||||
top_scope->flags &= ~SCOPE_NOSTACK;
|
||||
ruby_running = 1;
|
||||
}
|
||||
|
||||
|
@ -4652,7 +4654,7 @@ rb_yield_0(val, self, klass, flags, avalue)
|
|||
ruby_current_node = node;
|
||||
|
||||
PUSH_ITER(block->iter);
|
||||
PUSH_TAG(lambda ? PROT_NONE : PROT_YIELD);
|
||||
PUSH_TAG((flags & YIELD_BLOCK_ORPHAN) ? PROT_NONE : PROT_YIELD);
|
||||
if ((state = EXEC_TAG()) == 0) {
|
||||
redo:
|
||||
if (nd_type(node) == NODE_CFUNC || nd_type(node) == NODE_IFUNC) {
|
||||
|
@ -4684,9 +4686,10 @@ rb_yield_0(val, self, klass, flags, avalue)
|
|||
state = 0;
|
||||
result = prot_tag->retval;
|
||||
break;
|
||||
case TAG_RETURN:
|
||||
if (!lambda)
|
||||
case TAG_BREAK:
|
||||
if (TAG_DST()) {
|
||||
result = prot_tag->retval;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -6999,6 +7002,9 @@ rb_mod_modfunc(argc, argv, module)
|
|||
id = rb_to_id(argv[i]);
|
||||
for (;;) {
|
||||
body = search_method(m, id, &m);
|
||||
if (body == 0) {
|
||||
body = search_method(rb_cObject, id, &m);
|
||||
}
|
||||
if (body == 0 || body->nd_body == 0) {
|
||||
rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
|
||||
}
|
||||
|
@ -7983,6 +7989,7 @@ proc_invoke(proc, args, self, klass)
|
|||
Data_Get_Struct(proc, struct BLOCK, data);
|
||||
pcall = (data->flags & BLOCK_LAMBDA) ? YIELD_LAMBDA_CALL : 0;
|
||||
orphan = pcall ? 0 : block_orphan(data);
|
||||
if (orphan || pcall) pcall |= YIELD_BLOCK_ORPHAN;
|
||||
if (!pcall && RARRAY(args)->len == 1) {
|
||||
avalue = Qfalse;
|
||||
args = RARRAY(args)->ptr[0];
|
||||
|
@ -8122,6 +8129,7 @@ proc_arity(proc)
|
|||
}
|
||||
return INT2FIX(-1);
|
||||
}
|
||||
if (!(data->flags & BLOCK_LAMBDA)) return INT2FIX(-1);
|
||||
if (data->var == (NODE*)1) return INT2FIX(0);
|
||||
if (data->var == (NODE*)2) return INT2FIX(0);
|
||||
switch (nd_type(data->var)) {
|
||||
|
@ -8162,10 +8170,34 @@ proc_eq(self, other)
|
|||
if (data->body != data2->body) return Qfalse;
|
||||
if (data->var != data2->var) return Qfalse;
|
||||
if (data->frame.uniq != data2->frame.uniq) return Qfalse;
|
||||
if (data->dyna_vars != data2->dyna_vars) return Qfalse;
|
||||
if (data->flags != data2->flags) return Qfalse;
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* prc.hash => integer
|
||||
*
|
||||
* Return hash value corresponding to proc body.
|
||||
*/
|
||||
|
||||
static VALUE
|
||||
proc_hash(self, other)
|
||||
VALUE self;
|
||||
{
|
||||
struct BLOCK *data;
|
||||
long hash;
|
||||
|
||||
Data_Get_Struct(self, struct BLOCK, data);
|
||||
hash = (long)data->body;
|
||||
hash ^= (long)data->var;
|
||||
hash ^= data->frame.uniq << 16;
|
||||
hash ^= data->flags;
|
||||
|
||||
return INT2FIX(hash);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* prc.to_s => string
|
||||
|
@ -8459,6 +8491,29 @@ method_eq(method, other)
|
|||
return Qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* meth.hash => integer
|
||||
*
|
||||
* Return a hash value corresponding to the method object.
|
||||
*/
|
||||
|
||||
static VALUE
|
||||
method_hash(method)
|
||||
VALUE method;
|
||||
{
|
||||
struct METHOD *m;
|
||||
long hash;
|
||||
|
||||
Data_Get_Struct(method, struct METHOD, m);
|
||||
hash = (long)m->klass;
|
||||
hash ^= (long)m->rklass;
|
||||
hash ^= (long)m->recv;
|
||||
hash ^= (long)m->body;
|
||||
|
||||
return INT2FIX(hash);
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* meth.unbind => unbound_method
|
||||
|
@ -9092,6 +9147,8 @@ Init_Proc()
|
|||
rb_define_method(rb_cProc, "arity", proc_arity, 0);
|
||||
rb_define_method(rb_cProc, "[]", proc_call, -2);
|
||||
rb_define_method(rb_cProc, "==", proc_eq, 1);
|
||||
rb_define_method(rb_cProc, "eql?", proc_eq, 1);
|
||||
rb_define_method(rb_cProc, "hash", proc_hash, 0);
|
||||
rb_define_method(rb_cProc, "to_s", proc_to_s, 0);
|
||||
rb_define_method(rb_cProc, "to_proc", proc_to_self, 0);
|
||||
rb_define_method(rb_cProc, "binding", proc_binding, 0);
|
||||
|
@ -9103,6 +9160,8 @@ Init_Proc()
|
|||
rb_undef_alloc_func(rb_cMethod);
|
||||
rb_undef_method(CLASS_OF(rb_cMethod), "new");
|
||||
rb_define_method(rb_cMethod, "==", method_eq, 1);
|
||||
rb_define_method(rb_cMethod, "eql?", method_eq, 1);
|
||||
rb_define_method(rb_cMethod, "hash", method_hash, 0);
|
||||
rb_define_method(rb_cMethod, "clone", method_clone, 0);
|
||||
rb_define_method(rb_cMethod, "call", method_call, -1);
|
||||
rb_define_method(rb_cMethod, "[]", method_call, -1);
|
||||
|
@ -9117,6 +9176,8 @@ Init_Proc()
|
|||
rb_undef_alloc_func(rb_cUnboundMethod);
|
||||
rb_undef_method(CLASS_OF(rb_cUnboundMethod), "new");
|
||||
rb_define_method(rb_cUnboundMethod, "==", method_eq, 1);
|
||||
rb_define_method(rb_cUnboundMethod, "eql?", method_eq, 1);
|
||||
rb_define_method(rb_cUnboundMethod, "hash", method_hash, 0);
|
||||
rb_define_method(rb_cUnboundMethod, "clone", method_clone, 0);
|
||||
rb_define_method(rb_cUnboundMethod, "arity", method_arity, 0);
|
||||
rb_define_method(rb_cUnboundMethod, "inspect", method_inspect, 0);
|
||||
|
|
|
@ -561,8 +561,10 @@ The variable ruby-indent-level controls the amount of indentation.
|
|||
(defun ruby-indent-size (pos nest)
|
||||
(+ pos (* (or nest 1) ruby-indent-level)))
|
||||
|
||||
;;; maybe obsolete
|
||||
(defconst ruby-assign-re "\\s *\\(&&\\|||\\|<<\\|>>\\|[-+*/%&|^]\\)?=\\s *")
|
||||
|
||||
;;; maybe obsolete
|
||||
(defun ruby-beginning-of-arg (start end)
|
||||
(save-restriction
|
||||
(narrow-to-region start (1+ end))
|
||||
|
@ -586,6 +588,7 @@ The variable ruby-indent-level controls the amount of indentation.
|
|||
(if beg (setq beg nil arg (point))))
|
||||
((looking-at ruby-operator-re)
|
||||
(goto-char (match-end 0))
|
||||
(echo "foo %s %s" arg beg)
|
||||
(if beg (setq beg nil arg (match-end 0))))
|
||||
((not (eq (char-syntax (char-after)) ?\())
|
||||
(setq start (point)))))
|
||||
|
@ -731,7 +734,9 @@ The variable ruby-indent-level controls the amount of indentation.
|
|||
(not (bobp)))
|
||||
(save-excursion
|
||||
(widen)
|
||||
(ruby-beginning-of-arg (or begin parse-start) (point))
|
||||
(goto-char (or begin parse-start))
|
||||
(skip-syntax-forward " ")
|
||||
;; (ruby-beginning-of-arg (or begin parse-start) (point))
|
||||
(current-column)))
|
||||
(t
|
||||
(+ indent ruby-indent-level))))))))
|
||||
|
@ -832,7 +837,9 @@ An end of a defun is found by moving forward from the beginning of one."
|
|||
(skip-chars-forward ",.:;|&^~=!?\\+\\-\\*")
|
||||
(looking-at "\\s("))
|
||||
(goto-char (scan-sexps (point) 1)))
|
||||
((looking-at ruby-block-beg-re)
|
||||
((and (looking-at ruby-block-beg-re)
|
||||
(not (eq (char-before (point)) ?.))
|
||||
(not (eq (char-before (point)) ?:)))
|
||||
(ruby-end-of-block)
|
||||
(forward-word 1))
|
||||
((looking-at "\\(\\$\\|@@?\\)?\\sw")
|
||||
|
|
5
parse.y
5
parse.y
|
@ -4244,7 +4244,10 @@ yylex()
|
|||
tokadd(c);
|
||||
tokfix();
|
||||
yylval.id = rb_intern(tok());
|
||||
/* xxx shouldn't check if valid option variable */
|
||||
if (!is_global_id(yylval.id)) {
|
||||
rb_compile_error("invalid global variable `%s'", rb_id2name(yylval.id));
|
||||
return 0;
|
||||
}
|
||||
return tGVAR;
|
||||
|
||||
case '&': /* $&: last match */
|
||||
|
|
11
ruby.c
11
ruby.c
|
@ -1048,6 +1048,16 @@ verbose_setter(val, id, variable)
|
|||
ruby_verbose = RTEST(val) ? Qtrue : val;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
opt_W_getter(val, id)
|
||||
VALUE val;
|
||||
ID id;
|
||||
{
|
||||
if (ruby_verbose == Qnil) return INT2FIX(0);
|
||||
if (ruby_verbose == Qfalse) return INT2FIX(1);
|
||||
if (ruby_verbose == Qtrue) return INT2FIX(2);
|
||||
}
|
||||
|
||||
void
|
||||
ruby_prog_init()
|
||||
{
|
||||
|
@ -1057,6 +1067,7 @@ ruby_prog_init()
|
|||
rb_define_hooked_variable("$VERBOSE", &ruby_verbose, 0, verbose_setter);
|
||||
rb_define_hooked_variable("$-v", &ruby_verbose, 0, verbose_setter);
|
||||
rb_define_hooked_variable("$-w", &ruby_verbose, 0, verbose_setter);
|
||||
rb_define_virtual_variable("$-W", opt_W_getter, 0);
|
||||
rb_define_variable("$DEBUG", &ruby_debug);
|
||||
rb_define_variable("$-d", &ruby_debug);
|
||||
rb_define_readonly_variable("$-p", &do_print);
|
||||
|
|
|
@ -1120,6 +1120,20 @@ end
|
|||
ljump_test(false, get_block{break})
|
||||
ljump_test(true, lambda{break})
|
||||
|
||||
def exit_value_test(&block)
|
||||
block.call
|
||||
rescue LocalJumpError
|
||||
$!.exit_value
|
||||
end
|
||||
|
||||
test_ok(45, exit_value_test{break 45})
|
||||
|
||||
test_ok(55, begin
|
||||
get_block{break 55}.call
|
||||
rescue LocalJumpError
|
||||
$!.exit_value
|
||||
end)
|
||||
|
||||
test_ok(block.arity == -1)
|
||||
test_ok(lambda.arity == -1)
|
||||
test_ok(lambda{||}.arity == 0)
|
||||
|
@ -1140,7 +1154,7 @@ test_ok(return_in_lambda())
|
|||
|
||||
def marity_test(m)
|
||||
method = method(m)
|
||||
test_ok(method.arity == method.to_proc.arity)
|
||||
test_ok(method.arity == method.to_proc.arity, 2)
|
||||
end
|
||||
marity_test(:test_ok)
|
||||
marity_test(:marity_test)
|
||||
|
|
Loading…
Reference in a new issue