summaryrefslogtreecommitdiff
path: root/class.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-06-27 07:48:50 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-06-27 07:48:50 +0000
commit8ddbbb33242f413845079b0274c28331cb4aa0f5 (patch)
tree522b12dada77b09073a58130c99c77d62c895b87 /class.c
parent8634544fa74be0995582bc8056763fcfd38a0702 (diff)
Module#prepend
* class.c (rb_prepend_module): prepend module into another module. * eval.c (rb_mod_prepend): new method Module#prepend. [Feature #1102] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36234 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'class.c')
-rw-r--r--class.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/class.c b/class.c
index daaf401497..fc3b483735 100644
--- a/class.c
+++ b/class.c
@@ -56,6 +56,7 @@ class_alloc(VALUE flags, VALUE klass)
RCLASS_CONST_TBL(obj) = 0;
RCLASS_M_TBL(obj) = 0;
RCLASS_SUPER(obj) = 0;
+ RCLASS_ORIGIN(obj) = (VALUE)obj;
RCLASS_IV_INDEX_TBL(obj) = 0;
return (VALUE)obj;
}
@@ -687,6 +688,8 @@ rb_include_module(VALUE klass, VALUE module)
break;
}
}
+ if (c == klass)
+ c = RCLASS_ORIGIN(klass);
c = RCLASS_SUPER(c) = include_class_new(module, RCLASS_SUPER(c));
if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries)
changed = 1;
@@ -696,6 +699,45 @@ rb_include_module(VALUE klass, VALUE module)
if (changed) rb_clear_cache();
}
+void
+rb_prepend_module(VALUE klass, VALUE module)
+{
+ VALUE p, c, origin;
+
+ rb_frozen_class_p(klass);
+ if (!OBJ_UNTRUSTED(klass)) {
+ rb_secure(4);
+ }
+
+ Check_Type(module, T_MODULE);
+
+ OBJ_INFECT(klass, module);
+ c = RCLASS_SUPER(klass);
+ if (RCLASS_M_TBL(klass) == RCLASS_M_TBL(module))
+ rb_raise(rb_eArgError, "cyclic include detected");
+ for (p = c; p; p = RCLASS_SUPER(p)) {
+ if (BUILTIN_TYPE(p) == T_ICLASS) {
+ if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) {
+ rb_raise(rb_eArgError, "already prepended module");
+ }
+ }
+ }
+ origin = RCLASS_ORIGIN(klass);
+ if (origin == klass) {
+ origin = class_alloc(T_ICLASS, rb_cClass);
+ RCLASS_SUPER(origin) = RCLASS_SUPER(klass);
+ RCLASS_SUPER(klass) = origin;
+ RCLASS_ORIGIN(klass) = origin;
+ RCLASS_M_TBL(origin) = RCLASS_M_TBL(klass);
+ RCLASS_M_TBL(klass) = 0;
+ c = origin;
+ }
+ RCLASS_SUPER(klass) = include_class_new(module, c);
+ if (RMODULE_M_TBL(module) && RMODULE_M_TBL(module)->num_entries) {
+ rb_clear_cache_by_class(klass);
+ }
+}
+
/*
* call-seq:
* mod.included_modules -> array