mixology 0.2.0-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -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