summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-02-19 09:27:49 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-02-19 09:27:49 +0000
commit884efe7c5ecfe5bf0621008b7a535729b4c07b97 (patch)
tree0380cb0e4887dd83e1047c42285c3eb6e3ae9856
parentd22fc7c4d8849c86774b049bd6ef02005187c671 (diff)
* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3506 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog11
-rw-r--r--eval.c73
-rw-r--r--gc.c4
-rw-r--r--node.h2
-rw-r--r--parse.y27
5 files changed, 93 insertions, 24 deletions
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 <nobu.nokada@softhome.net>
+
+ * 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 <matz@ruby-lang.org>
* 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 <node> singleton strings string string1 xstring regexp
%type <node> string_contents xstring_contents string_content
%type <node> words qwords word_list qword_list word
-%type <node> literal numeric dsym
+%type <node> literal numeric dsym cbase cpath
%type <node> bodystmt compstmt stmts stmt expr arg primary command command_call method_call
%type <node> expr_value arg_value primary_value
%type <node> 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 = $<num>4;
in_single = $<num>6;
}
- | kMODULE cname
+ | kMODULE cpath
{
if (in_def || in_single)
yyerror("module definition in method body");