From: nobu.nokada@... Date: 2003-02-19T14:27:18+09:00 Subject: Re: module This::Encompassing::That Hi, At Wed, 19 Feb 2003 13:05:48 +0900, Yukihiro Matsumoto wrote: > |> tmp = D > |> module A > |> class B < tmp > |> end > |> end > | > |Isn't > | > | class A::B < ::D > | > |equivalent here? > > Yes. But it can be something like > > module Foo > class A::B < D > end > end > > where search for D start from Foo, then toplevel (Object). Like this? Index: node.h =================================================================== RCS file: //sharui/cvs/ruby/src/ruby/node.h,v retrieving revision 1.41 diff -u -2 -p -r1.41 node.h --- node.h 16 Jan 2003 07:34:01 -0000 1.41 +++ node.h 19 Feb 2003 01:16:44 -0000 @@ -219,5 +219,5 @@ typedef struct RNode { #define nd_argc u2.argc -#define nd_cname u1.id +#define nd_cpath u1.node #define nd_super u3.node Index: eval.c =================================================================== RCS file: //sharui/cvs/ruby/src/ruby/eval.c,v retrieving revision 1.397 diff -u -2 -p -r1.397 eval.c --- eval.c 18 Feb 2003 14:30:17 -0000 1.397 +++ eval.c 19 Feb 2003 01:37:51 -0000 @@ -2220,4 +2220,26 @@ svalue_to_avalue(v) } +static VALUE +class_prefix(self, cpath) + VALUE self; + NODE *cpath; +{ + if (!cpath) { + rb_bug("class path missing"); + } + if (cpath->nd_head) { + return rb_eval(self, cpath->nd_head); + } + else if (nd_type(cpath) == NODE_COLON2) { + return ruby_cbase; + } + else if (ruby_wrapper) { + return ruby_wrapper; + } + else { + return rb_cObject; + } +} + static void return_check _((void)); #define return_value(v) do {\ @@ -3301,5 +3323,6 @@ rb_eval(self, n) case NODE_CLASS: { - VALUE super, klass, tmp; + VALUE super, klass, tmp, cbase; + ID cname; if (NIL_P(ruby_cbase)) { @@ -3313,12 +3336,14 @@ rb_eval(self, n) } - if ((ruby_cbase == rb_cObject) && rb_autoload_defined(node->nd_cname)) { - rb_autoload_load(node->nd_cname); + cbase = class_prefix(self, node->nd_cpath); + cname = node->nd_cpath->nd_mid; + if ((cbase == rb_cObject) && rb_autoload_defined(cname)) { + rb_autoload_load(cname); } - if (rb_const_defined_at(ruby_cbase, node->nd_cname)) { - klass = rb_const_get(ruby_cbase, node->nd_cname); + if (rb_const_defined_at(cbase, cname)) { + klass = rb_const_get(cbase, cname); if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", - rb_id2name(node->nd_cname)); + rb_id2name(cname)); } if (super) { @@ -3336,7 +3361,7 @@ rb_eval(self, n) override_class: if (!super) super = rb_cObject; - klass = rb_define_class_id(node->nd_cname, super); - rb_set_class_path(klass,ruby_cbase,rb_id2name(node->nd_cname)); - rb_const_set(ruby_cbase, node->nd_cname, klass); + klass = rb_define_class_id(cname, super); + rb_set_class_path(klass, cbase, rb_id2name(cname)); + rb_const_set(cbase, cname, klass); } if (ruby_wrapper) { @@ -3351,17 +3376,20 @@ rb_eval(self, n) case NODE_MODULE: { - VALUE module; + VALUE module, cbase; + ID cname; if (NIL_P(ruby_cbase)) { rb_raise(rb_eTypeError, "no outer class/module"); } - if ((ruby_cbase == rb_cObject) && rb_autoload_defined(node->nd_cname)) { - rb_autoload_load(node->nd_cname); + cbase = class_prefix(self, node->nd_cpath); + cname = node->nd_cpath->nd_mid; + if ((cbase == rb_cObject) && rb_autoload_defined(cname)) { + rb_autoload_load(cname); } - if (rb_const_defined_at(ruby_cbase, node->nd_cname)) { - module = rb_const_get(ruby_cbase, node->nd_cname); + if (rb_const_defined_at(cbase, cname)) { + module = rb_const_get(cbase, cname); if (TYPE(module) != T_MODULE) { rb_raise(rb_eTypeError, "%s is not a module", - rb_id2name(node->nd_cname)); + rb_id2name(cname)); } if (ruby_safe_level >= 4) { @@ -3370,7 +3398,7 @@ rb_eval(self, n) } else { - module = rb_define_module_id(node->nd_cname); - rb_set_class_path(module,ruby_cbase,rb_id2name(node->nd_cname)); - rb_const_set(ruby_cbase, node->nd_cname, module); + module = rb_define_module_id(cname); + rb_set_class_path(module, cbase, rb_id2name(cname)); + rb_const_set(cbase, cname, module); } if (ruby_wrapper) { Index: gc.c =================================================================== RCS file: //sharui/cvs/ruby/src/ruby/gc.c,v retrieving revision 1.121 diff -u -2 -p -r1.121 gc.c --- gc.c 31 Jan 2003 04:00:15 -0000 1.121 +++ gc.c 19 Feb 2003 03:13:56 -0000 @@ -649,4 +649,5 @@ rb_gc_mark_children(ptr) case NODE_RESCUE: case NODE_RESBODY: + case NODE_CLASS: rb_gc_mark((VALUE)obj->as.node.u2.node); /* fall through */ @@ -685,4 +686,5 @@ rb_gc_mark_children(ptr) case NODE_OP_ASGN_OR: case NODE_OP_ASGN_AND: + case NODE_MODULE: rb_gc_mark((VALUE)obj->as.node.u1.node); /* fall through */ @@ -697,5 +699,4 @@ rb_gc_mark_children(ptr) case NODE_CVDECL: case NODE_CVASGN: - case NODE_MODULE: case NODE_COLON3: case NODE_OPT_N: @@ -720,5 +721,4 @@ rb_gc_mark_children(ptr) case NODE_SCOPE: /* 2,3 */ - case NODE_CLASS: case NODE_BLOCK_PASS: rb_gc_mark((VALUE)obj->as.node.u3.node); Index: parse.y =================================================================== RCS file: //sharui/cvs/ruby/src/ruby/parse.y,v retrieving revision 1.255 diff -u -2 -p -r1.255 parse.y --- parse.y 13 Feb 2003 09:11:08 -0000 1.255 +++ parse.y 19 Feb 2003 05:15:58 -0000 @@ -241,5 +241,5 @@ static void top_local_setup(); %type string_contents xstring_contents string_content %type words qwords word_list qword_list word -%type literal numeric dsym +%type literal numeric dsym cbase cpath %type bodystmt compstmt stmts stmt expr arg primary command command_call method_call %type expr_value arg_value primary_value @@ -838,4 +838,25 @@ cname : tIDENTIFIER ; +cbase : tCOLON3 cname + { + $$ = NEW_COLON3($2); + } + | cname + { + $$ = NEW_CONST($1); + } + | cbase tCOLON2 cname + { + $$ = NEW_COLON2($1, $3); + } + ; + +cpath : cbase + { + if (nd_type($$ = $1) == NODE_CONST) + $$ = NEW_COLON2(0, $$->nd_vid); + } + ; + fname : tIDENTIFIER | tCONSTANT @@ -1526,5 +1547,5 @@ primary : literal fixpos($$, $2); } - | kCLASS cname superclass + | kCLASS cpath superclass { if (in_def || in_single) @@ -1564,5 +1585,5 @@ primary : literal in_single = $6; } - | kMODULE cname + | kMODULE cpath { if (in_def || in_single) -- Nobu Nakada