Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add partial implementation of Module#prepend

  • Loading branch information...
commit 352461791cf35e68cd8bacd1f77e9bf14e162574 1 parent 48e6c1e
@LTe LTe authored
Showing with 82 additions and 0 deletions.
  1. +14 −0 kernel/alpha.rb
  2. +68 −0 kernel/delta/module.rb
View
14 kernel/alpha.rb
@@ -486,6 +486,12 @@ def append_features(mod)
#
def included(mod); end
+ # Hook method called on Module when another Module is .prepend'd into it.
+ #
+ # Override for module-specific behaviour.
+ #
+ def prepended(mod); end
+
# :internal:
#
# Basic version of .include used in kernel code.
@@ -700,6 +706,14 @@ def attach_to(cls)
# :internal:
#
+ # Inject self before class
+ #
+ def attach_before(cls)
+ @superclass = cls
+ end
+
+ # :internal:
+ #
# Name of the included Module.
#
def name
View
68 kernel/delta/module.rb
@@ -85,6 +85,74 @@ def include(*modules)
self
end
+ def prepend(*modules)
+ modules.reverse_each do |mod|
+ if !mod.kind_of?(Module) or mod.kind_of?(Class)
+ raise TypeError, "wrong argument type #{mod.class} (expected Module)"
+ end
+
+ Rubinius.privately do
+ mod.prepend_features self
+ end
+
+ Rubinius.privately do
+ mod.prepended self
+ end
+ end
+ end
+
+ def prepend_features(klass)
+ unless klass.kind_of? Module
+ raise TypeError, "invalid argument class #{klass.class}, expected Module"
+ end
+
+ mod = self
+ changed = false
+
+ # Check for a cyclic include
+ if mod == klass
+ raise ArgumentError, "cyclic include detected"
+ end
+
+ while mod
+ add = true
+ k = klass.direct_superclass
+
+ while k
+ if k.kind_of? Rubinius::IncludedModule
+ if k == mod
+ add = false
+ break
+ end
+ end
+
+ k = k.direct_superclass
+ end
+
+ if add
+ if mod.kind_of? Rubinius::IncludedModule
+ original_mod = mod.module
+ else
+ original_mod = mod
+ end
+
+ Rubinius::IncludedModule.new(original_mod).attach_before klass
+
+ changed = true
+ end
+
+ mod = mod.direct_superclass
+ end
+
+ if changed
+ method_table.each do |meth, obj, vis|
+ Rubinius::VM.reset_method_cache meth
+ end
+ end
+
+ return self
+ end
+
# Add all constants, instance methods and module variables
# of this Module and all Modules that this one includes to +klass+
#
Please sign in to comment.
Something went wrong with that request. Please try again.