mixology 0.2.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,99 @@
1
+ require "rake"
2
+ require 'rake/clean'
3
+ require 'rake/gempackagetask'
4
+ require "rake/testtask"
5
+
6
+ desc "clean, compile, test"
7
+ task :default => %w[clean compile test]
8
+
9
+ Rake::TestTask.new("test") do |t|
10
+ t.pattern = "test/**/*_test.rb"
11
+ end
12
+
13
+ desc "Builds the extension"
14
+ if RUBY_PLATFORM =~ /java/
15
+ task :compile => :compile_java
16
+ else
17
+ task :compile => %W[ext/mixology/Makefile ext/mixology/mixology.#{Config::CONFIG['DLEXT']}]
18
+ end
19
+
20
+ file "ext/mixology/Makefile" => ["ext/mixology/extconf.rb"] do
21
+ Dir.chdir("ext/mixology") do
22
+ ruby "extconf.rb"
23
+ end
24
+ end
25
+
26
+ file "ext/mixology/mixology.#{Config::CONFIG['DLEXT']}" do
27
+ Dir.chdir("ext/mixology") do
28
+ sh "make"
29
+ end
30
+ cp "ext/mixology/mixology.#{Config::CONFIG['DLEXT']}", "lib"
31
+ end
32
+
33
+ CLEAN.include %w[ext/mixology/Makefile ext/mixology/mixology.bundle ext/mixology/mixology.so lib/mixology.bundle lib/mixology.so ext/mixology/mixology.o]
34
+ CLEAN.include %w[ext/mixology/MixableService.class ext/mixology/mixable.jar lib/mixology.jar]
35
+
36
+ specification = Gem::Specification.new do |s|
37
+ s.name = "mixology"
38
+ s.summary = "Mixology enables objects to mixin and unmix modules."
39
+ s.version = "0.2.0"
40
+ s.author = "anonymous z, Pat Farley, Dan Manges"
41
+ s.description = s.summary
42
+ s.homepage = "http://mixology.rubyforge.org"
43
+ s.rubyforge_project = "mixology"
44
+ s.has_rdoc = false
45
+ s.autorequire = "mixology"
46
+ s.files = FileList['ext/**/*.{c,rb}', '{lib,test}/**/*.rb', '^[A-Z]+$', 'Rakefile'].to_a
47
+ if RUBY_PLATFORM =~ /mswin/
48
+ s.platform = Gem::Platform::WIN32
49
+ s.files += ["lib/mixology.so"]
50
+ elsif RUBY_PLATFORM =~ /java/
51
+ s.platform = "java"
52
+ s.files += ["lib/mixology.jar"]
53
+ else
54
+ s.platform = Gem::Platform::RUBY
55
+ s.extensions = FileList["ext/**/extconf.rb"].to_a
56
+ end
57
+ end
58
+ Rake::GemPackageTask.new(specification) do |package|
59
+ package.need_zip = false
60
+ package.need_tar = false
61
+ end
62
+
63
+ desc "Compiles the JRuby extension"
64
+ task :compile_java do
65
+ Dir.chdir("ext/mixology") do
66
+ sh %{javac -source 1.5 -target 1.5 -classpath $JRUBY_HOME/lib/jruby.jar MixologyService.java}
67
+ sh %{jar cf mixology.jar MixologyService.class}
68
+ cp "mixology.jar", "../../lib/mixology.jar"
69
+ end
70
+ end
71
+
72
+ desc "test against multiple ruby implementations"
73
+ task :test_multi do
74
+ # this is specific to how I have Ruby installed on my machine -Dan
75
+ jruby = %w[1.1.3 1.1.4]
76
+ mri = %w[1.8.6-p368 1.9.1-p129]
77
+ failed = false
78
+ test_implementation = proc do |implementation, command|
79
+ print "#{implementation}: "
80
+ output = `#{command} 2>&1`
81
+ if $?.success? && output =~ /\d\d+ tests.*0 failures, 0 errors/
82
+ puts "PASS"
83
+ else
84
+ puts "FAIL"
85
+ failed = true
86
+ end
87
+ end
88
+ jruby.each do |jruby_version|
89
+ test_implementation.call(
90
+ "JRuby #{jruby_version}",
91
+ "JRUBY_HOME=/usr/local/jruby-#{jruby_version} /usr/local/jruby-#{jruby_version}/bin/jruby -S rake"
92
+ )
93
+ end
94
+ mri.each do |mri_version|
95
+ test_implementation.call "MRI #{mri_version}", "/usr/local/ruby-#{mri_version}/bin/rake"
96
+ end
97
+ fail if failed
98
+ end
99
+
@@ -0,0 +1,4 @@
1
+ require "mkmf"
2
+ dir_config "mixology"
3
+ $CPPFLAGS += " -DRUBY_19" if RUBY_VERSION =~ /1.9/
4
+ create_makefile "mixology"
@@ -0,0 +1,125 @@
1
+ #include "ruby.h"
2
+
3
+ /* cannot use ordinary CLASS_OF as it does not return an lvalue */
4
+ #define KLASS_OF(c) (RBASIC(c)->klass)
5
+
6
+ /* macros for backwards compatibility with 1.8 */
7
+ #ifndef RUBY_19
8
+ # define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
9
+ # define RCLASS_SUPER(c) (RCLASS(c)->super)
10
+ # define RCLASS_IV_TBL(c) (RCLASS(c)->iv_tbl)
11
+ #endif
12
+
13
+ #ifdef RUBY_19
14
+ static VALUE class_alloc(VALUE flags, VALUE klass)
15
+ {
16
+ rb_classext_t *ext = ALLOC(rb_classext_t);
17
+ NEWOBJ(obj, struct RClass);
18
+ OBJSETUP(obj, klass, flags);
19
+ obj->ptr = ext;
20
+ RCLASS_IV_TBL(obj) = 0;
21
+ RCLASS_M_TBL(obj) = 0;
22
+ RCLASS_SUPER(obj) = 0;
23
+ RCLASS_IV_INDEX_TBL(obj) = 0;
24
+ return (VALUE)obj;
25
+ }
26
+ #endif
27
+
28
+ static void remove_nested_module(VALUE klass, VALUE include_class)
29
+ {
30
+ if (KLASS_OF(RCLASS_SUPER(klass)) != KLASS_OF(RCLASS_SUPER(include_class))) {
31
+ return;
32
+ }
33
+ if (RCLASS_SUPER(RCLASS_SUPER(include_class)) && BUILTIN_TYPE(RCLASS_SUPER(include_class)) == T_ICLASS) {
34
+ remove_nested_module(RCLASS_SUPER(klass), RCLASS_SUPER(include_class));
35
+ }
36
+ RCLASS_SUPER(klass) = RCLASS_SUPER(RCLASS_SUPER(klass));
37
+ }
38
+
39
+ static VALUE rb_unmix(VALUE self, VALUE module)
40
+ {
41
+ VALUE klass;
42
+
43
+ /* check that module is valid */
44
+ if (TYPE(module) != T_MODULE)
45
+ rb_raise(rb_eArgError, "error: parameter must be a module");
46
+
47
+ for (klass = KLASS_OF(self); klass != rb_class_real(klass); klass = RCLASS_SUPER(klass)) {
48
+ VALUE super = RCLASS_SUPER(klass);
49
+ if (BUILTIN_TYPE(super) == T_ICLASS) {
50
+ if (KLASS_OF(super) == module) {
51
+ if (RCLASS_SUPER(module) && BUILTIN_TYPE(RCLASS_SUPER(module)) == T_ICLASS)
52
+ remove_nested_module(super, module);
53
+
54
+ RCLASS_SUPER(klass) = RCLASS_SUPER(RCLASS_SUPER(klass));
55
+ rb_clear_cache();
56
+ }
57
+ }
58
+ }
59
+ return self;
60
+ }
61
+
62
+ static void add_module(VALUE self, VALUE module)
63
+ {
64
+ VALUE super = RCLASS_SUPER(rb_singleton_class(self));
65
+
66
+ #ifdef RUBY_19
67
+ VALUE klass = class_alloc(T_ICLASS, rb_cClass);
68
+ #else
69
+ NEWOBJ(klass, struct RClass);
70
+ OBJSETUP(klass, rb_cClass, T_ICLASS);
71
+ #endif
72
+
73
+ if (BUILTIN_TYPE(module) == T_ICLASS) {
74
+ module = KLASS_OF(module);
75
+ }
76
+ if (!RCLASS_IV_TBL(module)) {
77
+ RCLASS_IV_TBL(module) = (void*)st_init_numtable();
78
+ }
79
+
80
+ RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
81
+ RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
82
+ RCLASS_SUPER(klass) = super;
83
+
84
+ if (TYPE(module) == T_ICLASS) {
85
+ KLASS_OF(klass) = KLASS_OF(module);
86
+ } else {
87
+ KLASS_OF(klass) = module;
88
+ }
89
+ OBJ_INFECT(klass, module);
90
+ OBJ_INFECT(klass, super);
91
+
92
+ RCLASS_SUPER(rb_singleton_class(self)) = (VALUE)klass;
93
+ }
94
+
95
+ static VALUE rb_mixin(VALUE self, VALUE module)
96
+ {
97
+ VALUE nested_modules;
98
+ int index;
99
+
100
+ /* check that module is valid */
101
+ if (TYPE(module) != T_MODULE)
102
+ rb_raise(rb_eArgError, "error: parameter must be a module");
103
+
104
+ rb_unmix(self, module);
105
+ nested_modules = rb_mod_included_modules(module);
106
+
107
+ for (index = RARRAY_LEN(nested_modules); index > 0; index--) {
108
+ VALUE nested_module = RARRAY_PTR(nested_modules)[index - 1];
109
+ add_module(self, nested_module);
110
+ }
111
+
112
+ add_module(self, module);
113
+
114
+ rb_clear_cache();
115
+ return self;
116
+ }
117
+
118
+ void Init_mixology()
119
+ {
120
+ VALUE Mixology = rb_define_module("Mixology");
121
+
122
+ rb_define_method(Mixology, "mixin", rb_mixin, 1);
123
+ rb_define_method(Mixology, "unmix", rb_unmix, 1);
124
+ rb_include_module(rb_cObject, Mixology);
125
+ }
Binary file
@@ -0,0 +1,39 @@
1
+ module Mixology
2
+ def mixin(mod)
3
+ unmix mod
4
+ reset_method_cache
5
+ IncludedModule.new(mod).attach_to metaclass
6
+ reset_method_cache
7
+ self
8
+ end
9
+
10
+ def unmix(mod_to_unmix)
11
+ last_super = metaclass
12
+ this_super = metaclass.direct_superclass
13
+ while this_super
14
+ break if this_super == self.class
15
+ if (this_super == mod_to_unmix ||
16
+ this_super.respond_to?(:module) && this_super.module == mod_to_unmix)
17
+ reset_method_cache
18
+ last_super.superclass = this_super.direct_superclass
19
+ reset_method_cache
20
+ return self
21
+ else
22
+ last_super = this_super
23
+ this_super = this_super.direct_superclass
24
+ end
25
+ end
26
+ self
27
+ end
28
+
29
+ protected
30
+
31
+ def reset_method_cache
32
+ self.methods.each do |name|
33
+ name = self.metaclass.send(:normalize_name,name)
34
+ Rubinius::VM.reset_method_cache(name)
35
+ end
36
+ end
37
+ end
38
+
39
+ Object.send :include, Mixology
@@ -0,0 +1,183 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ class MixologyTest < Test::Unit::TestCase
4
+
5
+ def test_mixin
6
+ mixin = Module.new { def foo; "foo"; end }
7
+ object = Object.new
8
+ object.mixin mixin
9
+ assert_equal "foo", object.foo
10
+ end
11
+
12
+ def test_unmix
13
+ mixin = Module.new { def foo; "mixin"; end }
14
+ object = Class.new { def foo; "object"; end }.new
15
+ object.mixin mixin
16
+ assert_equal "mixin", object.foo
17
+ object.unmix mixin
18
+ assert_equal "object", object.foo
19
+ end
20
+
21
+ def test_mixin_twice
22
+ first_mixin = Module.new { def foo; "first"; end }
23
+ second_mixin = Module.new { def foo; "second"; end }
24
+ object = Object.new
25
+ object.mixin first_mixin
26
+ object.mixin second_mixin
27
+ assert_equal "second", object.foo
28
+ end
29
+
30
+ def test_mixin_to_class
31
+ mix = Module.new { def foo; "foo"; end }
32
+ klass = Class.new { mixin mix }
33
+ assert_equal "foo", klass.foo
34
+ end
35
+
36
+ def test_can_mixin_again
37
+ first_mixin = Module.new { def foo; "first"; end }
38
+ second_mixin = Module.new { def foo; "second"; end }
39
+ object = Object.new
40
+ object.mixin first_mixin
41
+ object.mixin second_mixin
42
+ object.mixin first_mixin
43
+ assert_equal "first", object.foo
44
+ end
45
+
46
+ def test_unmix_effects_limited_to_instance
47
+ mixin = Module.new { def foo; "mixin"; end }
48
+ object = Class.new {include mixin}.new
49
+ assert_equal "mixin", object.foo
50
+ object.unmix mixin
51
+ assert_equal "mixin", object.foo
52
+ end
53
+
54
+ def test_can_add_mod_to_an_instance_even_when_already_included_by_class
55
+ mixin = Module.new { def foo; "mixin"; end }
56
+ klass = Class.new {include mixin; def foo; "class"; end }
57
+ object = klass.new
58
+ assert_equal "class", object.foo
59
+ object.mixin mixin
60
+ assert_equal "mixin", object.foo
61
+ end
62
+
63
+ def test_included_modules_after_mixin
64
+ mixin = Module.new
65
+ object = Object.new
66
+ object.mixin mixin
67
+ assert_equal [mixin, Mixology, PP::ObjectMixin, Kernel], (class << object; self; end).included_modules
68
+ end
69
+
70
+ def test_included_modules_after_unmix
71
+ mixin = Module.new
72
+ object = Object.new
73
+ object.mixin mixin
74
+ object.unmix mixin
75
+ assert_equal [Mixology, PP::ObjectMixin, Kernel], (class << object; self; end).included_modules
76
+ end
77
+
78
+ def test_included_modules_after_remix
79
+ mixin_one = Module.new
80
+ mixin_two = Module.new
81
+ object = Object.new
82
+ object.mixin mixin_one
83
+ object.mixin mixin_two
84
+ assert_equal [mixin_two, mixin_one, Mixology, PP::ObjectMixin, Kernel], (class << object; self; end).included_modules
85
+ object.mixin mixin_one
86
+ assert_equal [mixin_one, mixin_two, Mixology, PP::ObjectMixin, Kernel], (class << object; self; end).included_modules
87
+ end
88
+
89
+ def test_mixin_returns_object
90
+ object = Object.new
91
+ mixin = Module.new
92
+ assert_equal object, object.mixin(mixin)
93
+ end
94
+
95
+ def test_unmix_returns_object
96
+ object = Object.new
97
+ mixin = Module.new
98
+ object.mixin mixin
99
+ assert_equal object, object.unmix(mixin)
100
+ end
101
+
102
+ def test_nested_modules_are_mixedin
103
+ if rubinius?
104
+ print "PENDING"; return
105
+ end
106
+ nested_module = Module.new { def foo; "foo"; end }
107
+ mixin = Module.new { include nested_module }
108
+ object = Object.new
109
+ object.mixin mixin
110
+ assert_equal [mixin, nested_module, Mixology, PP::ObjectMixin, Kernel], (class << object; self; end).included_modules
111
+ end
112
+
113
+ def test_nested_modules_are_mixedin_deeply
114
+ if rubinius?
115
+ print "PENDING"; return
116
+ end
117
+ nested_module_ultimate = Module.new
118
+ nested_module_penultimate = Module.new { include nested_module_ultimate }
119
+ nested_module = Module.new { include nested_module_penultimate }
120
+ mixin = Module.new { include nested_module }
121
+ object = Object.new
122
+ object.mixin mixin
123
+ assert_equal [mixin, nested_module, nested_module_penultimate, nested_module_ultimate, Mixology, PP::ObjectMixin, Kernel], (class << object; self; end).included_modules
124
+ end
125
+
126
+ def test_nested_modules_are_mixedin_even_if_already_mixed_in
127
+ if rubinius?
128
+ print "PENDING"; return
129
+ end
130
+ nested_module = Module.new { def foo; "foo"; end }
131
+ mixin = Module.new { include nested_module }
132
+ object = Object.new
133
+ object.mixin nested_module
134
+ object.mixin mixin
135
+ assert_equal [mixin, nested_module, nested_module, Mixology, PP::ObjectMixin, Kernel], (class << object; self; end).included_modules
136
+ end
137
+
138
+ def test_module_is_not_unmixed_if_it_is_outside_nested_chain
139
+ nested_module = Module.new
140
+ mixin = Module.new { include nested_module }
141
+ object = Object.new
142
+ object.mixin nested_module
143
+ object.mixin mixin
144
+ object.unmix mixin
145
+ assert_equal [nested_module, Mixology, PP::ObjectMixin, Kernel], (class << object; self; end).included_modules
146
+ end
147
+
148
+ def test_nested_modules_are_unmixed
149
+ nested_module = Module.new
150
+ mixin = Module.new { include nested_module }
151
+ object = Object.new
152
+ object.mixin mixin
153
+ object.unmix mixin
154
+ assert_equal [Mixology, PP::ObjectMixin, Kernel], (class << object; self; end).included_modules
155
+ end
156
+
157
+ def test_nested_modules_are_unmixed_deeply
158
+ nested_module_ultimate = Module.new
159
+ nested_module_penultimate = Module.new { include nested_module_ultimate }
160
+ nested_module = Module.new { include nested_module_penultimate }
161
+ mixin = Module.new { include nested_module }
162
+ object = Object.new
163
+ object.mixin mixin
164
+ object.unmix mixin
165
+ assert_equal [Mixology, PP::ObjectMixin, Kernel], (class << object; self; end).included_modules
166
+ end
167
+
168
+ def test_unrelated_modules_are_not_unmixed
169
+ unrelated = Module.new
170
+ nested_module = Module.new
171
+ mixin = Module.new { include nested_module }
172
+ object = Object.new
173
+ object.mixin unrelated
174
+ object.mixin mixin
175
+ object.unmix mixin
176
+ assert_equal [unrelated, Mixology, PP::ObjectMixin, Kernel], (class << object; self; end).included_modules
177
+ end
178
+
179
+ def rubinius?
180
+ defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx"
181
+ end
182
+
183
+ end
@@ -0,0 +1,10 @@
1
+ require "test/unit"
2
+ # In Ruby 1.9, require test/unit will implicitly require pp, we do it here explicitly to ensure compatibily.
3
+ require "pp"
4
+
5
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../lib"
6
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx"
7
+ require "mixology_rubinius"
8
+ else
9
+ require "mixology"
10
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ required_ruby_version: !ruby/object:Gem::Requirement
3
+ requirements:
4
+ - - '>='
5
+ - !ruby/object:Gem::Version
6
+ version: "0"
7
+ version:
8
+ email:
9
+ cert_chain: []
10
+
11
+ summary: Mixology enables objects to mixin and unmix modules.
12
+ post_install_message:
13
+ extra_rdoc_files: []
14
+
15
+ homepage: http://mixology.rubyforge.org
16
+ signing_key:
17
+ name: mixology
18
+ rdoc_options: []
19
+
20
+ autorequire: mixology
21
+ rubyforge_project: mixology
22
+ executables: []
23
+
24
+ description: Mixology enables objects to mixin and unmix modules.
25
+ specification_version: 2
26
+ default_executable:
27
+ files:
28
+ - ext/mixology/mixology.c
29
+ - ext/mixology/extconf.rb
30
+ - lib/mixology_rubinius.rb
31
+ - test/test_helper.rb
32
+ - test/mixology_test.rb
33
+ - Rakefile
34
+ - lib/mixology.jar
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - '>='
38
+ - !ruby/object:Gem::Version
39
+ version: "0"
40
+ version:
41
+ extensions: []
42
+
43
+ rubygems_version: 1.2.0
44
+ requirements: []
45
+
46
+ authors:
47
+ - anonymous z, Pat Farley, Dan Manges
48
+ date: 2009-08-24 05:00:00 +00:00
49
+ platform: java
50
+ test_files: []
51
+
52
+ version: !ruby/object:Gem::Version
53
+ version: 0.2.0
54
+ require_paths:
55
+ - lib
56
+ dependencies: []
57
+
58
+ bindir: bin
59
+ has_rdoc: false