Hi,

At Fri, 7 Feb 2003 18:00:35 +0900,
Yukihiro Matsumoto wrote:
> |> "private" does mean "can only be called without explicit receiver".
> |> This is the reason.
> |
> |It it a bad idea to relax the restriction, "can only be called
> |without explicit receiver or with `self' receiver"?
> 
> Hmm, interesting.  Let me consider this issue.

Forgot an example.  Error if the receiver isn't literally
`self', even if it actually equals self.

    private :x=
    def my
      self
    end
    def my_x(val)
      my.x = val	# NG
    end

And patch.


Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.392 diff -u -2 -p -r1.392 eval.c --- eval.c 7 Feb 2003 06:30:18 -0000 1.392 +++ eval.c 7 Feb 2003 08:14:53 -0000 @@ -1924,6 +1924,7 @@ is_defined(self, node, buf) goto check_bound; - case NODE_CALL: case NODE_ATTRASGN: + if (node->nd_recv == (NODE *)1) goto check_bound; + case NODE_CALL: PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { @@ -2746,13 +2747,21 @@ rb_eval(self, n) VALUE recv; int argc; VALUE *argv; /* used in SETUP_ARGS */ + int scope; TMP_PROTECT; BEGIN_CALLARGS; - recv = rb_eval(self, node->nd_recv); + if (node->nd_recv == (NODE *)1) { + recv = self; + scope = 1; + } + else { + recv = rb_eval(self, node->nd_recv); + scope = 0; + } SETUP_ARGS(node->nd_args); END_CALLARGS; SET_CURRENT_SOURCE(); - rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0); + rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,scope); result = argv[argc-1]; } @@ -4092,10 +4101,18 @@ assign(self, lhs, val, pcall) { VALUE recv; - recv = rb_eval(self, lhs->nd_recv); + int scope; + if (lhs->nd_recv == (NODE *)1) { + recv = self; + scope = 1; + } + else { + recv = rb_eval(self, lhs->nd_recv); + scope = 0; + } if (!lhs->nd_args) { /* attr set */ ruby_current_node = lhs; SET_CURRENT_SOURCE(); - rb_call(CLASS_OF(recv), recv, lhs->nd_mid, 1, &val, 0); + rb_call(CLASS_OF(recv), recv, lhs->nd_mid, 1, &val, scope); } else { @@ -4108,5 +4125,5 @@ assign(self, lhs, val, pcall) SET_CURRENT_SOURCE(); rb_call(CLASS_OF(recv), recv, lhs->nd_mid, - RARRAY(args)->len, RARRAY(args)->ptr, 0); + RARRAY(args)->len, RARRAY(args)->ptr, scope); } } Index: parse.y =================================================================== RCS file: /cvs/ruby/src/ruby/parse.y,v retrieving revision 1.254 diff -u -2 -p -r1.254 parse.y --- parse.y 5 Feb 2003 08:11:27 -0000 1.254 +++ parse.y 7 Feb 2003 08:17:19 -0000 @@ -1403,5 +1403,8 @@ primary : literal | primary_value '[' aref_args ']' { - $$ = NEW_CALL($1, tAREF, $3); + if (nd_type($1) == NODE_SELF) + $$ = NEW_FCALL(tAREF, $3); + else + $$ = NEW_CALL($1, tAREF, $3); } | tLBRACK aref_args ']' @@ -4628,7 +4631,13 @@ call_op(recv, id, narg, arg1) if (narg == 1) { value_expr(arg1); + arg1 = NEW_LIST(arg1); + } + else { + arg1 = 0; } - return NEW_CALL(recv, id, narg==1?NEW_LIST(arg1):0); + if (recv && nd_type(recv) == NODE_SELF) + return NEW_FCALL(id, arg1); + return NEW_CALL(recv, id, arg1); } @@ -4668,4 +4677,6 @@ match_gen(node1, node2) } + if (node1 && nd_type(node1) == NODE_SELF) + return NEW_FCALL(tMATCH, NEW_LIST(node2)); return NEW_CALL(node1, tMATCH, NEW_LIST(node2)); } @@ -4784,5 +4795,8 @@ aryset(recv, idx) NODE *recv, *idx; { - value_expr(recv); + if (recv && nd_type(recv) == NODE_SELF) + recv = (NODE *)1; + else + value_expr(recv); return NEW_ATTRASGN(recv, tASET, idx); } @@ -4802,5 +4816,8 @@ attrset(recv, id) ID id; { - value_expr(recv); + if (recv && nd_type(recv) == NODE_SELF) + recv = (NODE *)1; + else + value_expr(recv); return NEW_ATTRASGN(recv, rb_id_attrset(id), 0); } @@ -5318,4 +5335,5 @@ new_call(r,m,a) NODE *a; { + if (r && nd_type(r) == NODE_SELF) return new_fcall(m, a); if (a && nd_type(a) == NODE_BLOCK_PASS) { a->nd_iter = NEW_CALL(r,m,a->nd_head);
-- Nobu Nakada