diff --git a/ChangeLog b/ChangeLog index 05012a179d..122c34e583 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +Wed Feb 19 18:27:42 2003 Nobuyoshi Nakada + + * node.h (nd_cpath): nested class/module declaration. + [EXPREIMENTAL] + + * eval.c (rb_eval): ditto. + + * gc.c (rb_gc_mark_children): ditto. + + * parse.y (cpath): ditto. + Tue Feb 18 21:39:27 2003 Yukihiro Matsumoto * eval.c (rb_call0): should not report uninitialized warning by diff --git a/eval.c b/eval.c index cf56536d3c..410248a9a0 100644 --- a/eval.c +++ b/eval.c @@ -2219,6 +2219,37 @@ svalue_to_avalue(v) return tmp; } +static VALUE +class_prefix(self, cpath) + VALUE self; + NODE *cpath; +{ + if (!cpath) { + rb_bug("class path missing"); + } + if (cpath->nd_head) { + VALUE c = rb_eval(self, cpath->nd_head); + switch (TYPE(c)) { + case T_CLASS: + case T_MODULE: + break; + default: + rb_raise(rb_eTypeError, "%s is not a class/module", + RSTRING(rb_obj_as_string(c))->ptr); + } + return c; + } + 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 {\ if ((prot_tag->retval = (v)) == Qundef) {\ @@ -3300,7 +3331,8 @@ rb_eval(self, n) case NODE_CLASS: { - VALUE super, klass, tmp; + VALUE super, klass, tmp, cbase; + ID cname; if (NIL_P(ruby_cbase)) { rb_raise(rb_eTypeError, "no outer class/module"); @@ -3312,14 +3344,16 @@ rb_eval(self, n) super = 0; } - 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) { tmp = rb_class_real(RCLASS(klass)->super); @@ -3335,9 +3369,9 @@ rb_eval(self, n) else { 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) { rb_extend_object(klass, ruby_wrapper); @@ -3350,28 +3384,31 @@ 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) { rb_raise(rb_eSecurityError, "extending module prohibited"); } } 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) { rb_extend_object(module, ruby_wrapper); diff --git a/gc.c b/gc.c index 97ff44527e..49be3b1f6b 100644 --- a/gc.c +++ b/gc.c @@ -648,6 +648,7 @@ rb_gc_mark_children(ptr) case NODE_MASGN: case NODE_RESCUE: case NODE_RESBODY: + case NODE_CLASS: rb_gc_mark((VALUE)obj->as.node.u2.node); /* fall through */ case NODE_BLOCK: /* 1,3 */ @@ -684,6 +685,7 @@ rb_gc_mark_children(ptr) case NODE_MATCH3: case NODE_OP_ASGN_OR: case NODE_OP_ASGN_AND: + case NODE_MODULE: rb_gc_mark((VALUE)obj->as.node.u1.node); /* fall through */ case NODE_METHOD: /* 2 */ @@ -696,7 +698,6 @@ rb_gc_mark_children(ptr) case NODE_CDECL: case NODE_CVDECL: case NODE_CVASGN: - case NODE_MODULE: case NODE_COLON3: case NODE_OPT_N: case NODE_EVSTR: @@ -719,7 +720,6 @@ rb_gc_mark_children(ptr) break; case NODE_SCOPE: /* 2,3 */ - case NODE_CLASS: case NODE_BLOCK_PASS: rb_gc_mark((VALUE)obj->as.node.u3.node); rb_gc_mark((VALUE)obj->as.node.u2.node); diff --git a/node.h b/node.h index 5f997654a8..8b667853e5 100644 --- a/node.h +++ b/node.h @@ -218,7 +218,7 @@ typedef struct RNode { #define nd_cfnc u1.cfunc #define nd_argc u2.argc -#define nd_cname u1.id +#define nd_cpath u1.node #define nd_super u3.node #define nd_modl u1.id diff --git a/parse.y b/parse.y index 0c04a40bea..2d0682f929 100644 --- a/parse.y +++ b/parse.y @@ -240,7 +240,7 @@ static void top_local_setup(); %type singleton strings string string1 xstring regexp %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 %type if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure @@ -837,6 +837,27 @@ cname : tIDENTIFIER | tCONSTANT ; +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 | tFID @@ -1525,7 +1546,7 @@ primary : literal $$ = NEW_FOR($2, $5, $8); fixpos($$, $2); } - | kCLASS cname superclass + | kCLASS cpath superclass { if (in_def || in_single) yyerror("class definition in method body"); @@ -1563,7 +1584,7 @@ primary : literal in_def = $4; in_single = $6; } - | kMODULE cname + | kMODULE cpath { if (in_def || in_single) yyerror("module definition in method body");