summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-03-03 04:55:35 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-03-03 04:55:35 +0000
commit54a04074256fa85db5da3bf0041773ddc3391196 (patch)
tree73b38f7c4ca353aa285a5fa0935a142c7a73d16f
parente3b15cf111472455a75ec181ff676bf5d370038d (diff)
* 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
-rw-r--r--ChangeLog16
-rw-r--r--README.EXT2
-rw-r--r--eval.c77
-rw-r--r--misc/ruby-mode.el11
-rw-r--r--parse.y5
-rw-r--r--ruby.c11
-rw-r--r--sample/test.rb16
7 files changed, 125 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index 5bf40cf4fa..3a491d582e 100644
--- a/ChangeLog
+++ b/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
diff --git a/README.EXT b/README.EXT
index 3a37db4e11..4504e98bdc 100644
--- a/README.EXT
+++ b/README.EXT
@@ -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.
diff --git a/eval.c b/eval.c
index 292f6c8610..c4b8d463dd 100644
--- a/eval.c
+++ b/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,12 +8170,36 @@ 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
*
* Shows the unique identifier for this proc, along with
@@ -8460,6 +8492,29 @@ method_eq(method, other)
}
/*
+ * 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);
diff --git a/misc/ruby-mode.el b/misc/ruby-mode.el
index a52b00893d..dac90ee1a2 100644
--- a/misc/ruby-mode.el
+++ b/misc/ruby-mode.el
@@ -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")
diff --git a/parse.y b/parse.y
index c116605047..471c8a8d2f 100644
--- a/parse.y
+++ b/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 */
diff --git a/ruby.c b/ruby.c
index bf24defc03..995cd2f3a8 100644
--- a/ruby.c
+++ b/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);
diff --git a/sample/test.rb b/sample/test.rb
index d37c978774..fe39fc646f 100644
--- a/sample/test.rb
+++ b/sample/test.rb
@@ -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)