Implementation of Module#prepend#1848
Closed
LTe wants to merge 13 commits intorubinius:masterfrom
LTe:prepend
Closed
Implementation of Module#prepend#1848LTe wants to merge 13 commits intorubinius:masterfrom LTe:prepend
LTe wants to merge 13 commits intorubinius:masterfrom
LTe:prepend
Conversation
Member
|
Your specs need a proper version guard for 2.0 so they don't fail on 1.8 and 1.9. I don't think we need prepend in kernel/alpha.rb as I don't expect us to be using it in Rubinius itself, so it doesn't need to be available to load the kernel. The rest I haven't looked into yet. |
Use ruby guard. Test only for ruby => 2.0
Method attach_before should remember last parent. Without this we can use prepend only once.
Developer can implement that method and put the logic in method
Contributor
Author
|
@dbussink very nice implementation of Module#prepend. I used my specs to validate your solution module ModuleSpecs
if RUBY_VERSION > "1.9.3"
module PrependModules
module M0
def m1; [:M0] end
end
module M1
def m1; [:M1, *super] end
end
module M2
def m1; [:M2, *super] end
end
M3 = Module.new do
def m1; [:M3, *super] end
end
module M4
def m1; [:M4, *super] end
end
class C
def m1; end
end
class C0 < C
include M0
prepend M1
def m1; [:C0, *super] end
end
class C1 < C0
prepend M2, M3
include M4
def m1; [:C1, *super] end
end
end
module ModuleToPrepend
def m
result = super
[:m, result]
end
end
class ClassToPrepend
prepend ModuleToPrepend
def m
:c
end
end
end
end
class Object
def labeled_module(name, &block)
Module.new do
singleton_class.class_eval {define_method(:to_s) {name}}
class_eval(&block) if block
end
end
def labeled_class(name, superclass = Object, &block)
Class.new(superclass) do
singleton_class.class_eval {define_method(:to_s) {name}}
class_eval(&block) if block
end
end
end
ruby_version_is "2.0" do
describe "Module#prepend" do
it "prepends modules in proper sequence" do
obj = ModuleSpecs::PrependModules::C0.new
obj.m1.should == [:M1,:C0,:M0]
obj = ModuleSpecs::PrependModules::C1.new
obj.m1.should == [:M2,:M3,:C1,:M4,:M1,:C0,:M0]
end
it "returns proper prepend module ancestors" do
m0 = labeled_module("m0") {def x; [:m0, *super] end}
m1 = labeled_module("m1") {def x; [:m1, *super] end; prepend m0}
m2 = labeled_module("m2") {def x; [:m2, *super] end; prepend m1}
c0 = labeled_class("c0") {def x; [:c0] end}
c1 = labeled_class("c1") {def x; [:c1] end; prepend m2}
c2 = labeled_class("c2", c0) {def x; [:c2, *super] end; include m2}
m1.ancestors.should == [m0, m1]
c1.ancestors[0, 4].should == [m0, m1, m2, c1]
m2.ancestors.should == [m0, m1, m2]
c1.new.x.should == [:m0, :m1, :m2, :c1]
c2.ancestors[0, 5].should == [c2, m0, m1, m2, c0]
c2.new.x.should == [:c2, :m0, :m1, :m2, :c0]
end
it "updates ancestors after prepend" do
m = Module.new
m1 = Module.new
c = Class.new { prepend m }
c1 = Class.new(c)
c1.ancestors.should include(m)
c1.ancestors.should_not include(m1)
c.send(:prepend, m1)
c1.ancestors.should include(m1)
end
end
endIn result |
Contributor
|
Can you open an issue for that / open a pull request with the additional specs in it? If it's just a commit comment, we're going to forget about it. |
Contributor
|
Probably better to start with a new pull request / issue than trying to rework this one. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ruby 2.0.0
This is only partial implementation of this feature. I don't know how change superclass chain. I found in Rubinius code. In this case we need create root for
IncludedModuleIn MRI implementation each
RClasshave origin field. On start origin points to itself. But after prepend interpreter allocate memory for new class and create another.So klass is still on top but have new origin. Little tricky for me :)
Someone can help me with
Module#prependimplementation? Maybe Rubinius internals are not ready forprepend. Any advice appreciated.