diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-03-03 04:55:35 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-03-03 04:55:35 +0000 |
commit | 54a04074256fa85db5da3bf0041773ddc3391196 (patch) | |
tree | 73b38f7c4ca353aa285a5fa0935a142c7a73d16f | |
parent | e3b15cf111472455a75ec181ff676bf5d370038d (diff) | |
download | ruby-54a04074256fa85db5da3bf0041773ddc3391196.tar.gz |
* 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-- | ChangeLog | 16 | ||||
-rw-r--r-- | README.EXT | 2 | ||||
-rw-r--r-- | eval.c | 77 | ||||
-rw-r--r-- | misc/ruby-mode.el | 11 | ||||
-rw-r--r-- | parse.y | 5 | ||||
-rw-r--r-- | ruby.c | 11 | ||||
-rw-r--r-- | sample/test.rb | 16 |
7 files changed, 125 insertions, 13 deletions
@@ -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. @@ -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") @@ -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 */ @@ -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) |