remix 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,2 @@
1
+ 25/10/2010 version 0.1.0
2
+ * release!
data/README.markdown ADDED
@@ -0,0 +1,40 @@
1
+ Remix
2
+ --------------
3
+
4
+ (c) John Mair (banisterfiend)
5
+ MIT license
6
+
7
+ Makes inheritance chains read/write
8
+
9
+ ** This is BETA software and has not yet been thoroughly tested, use
10
+ at own risk **
11
+
12
+ Currently supports:
13
+
14
+ * include_at(index)
15
+ * include_before(BeforeMod, Mod)
16
+ * include_after(AfterMod, Mod)
17
+ * swap_modules(Mod1, Mod2)
18
+ * remove_module(Mod)
19
+ * ...more to come!
20
+
21
+ example:
22
+
23
+ module M end
24
+
25
+ class A; end
26
+
27
+ class B < A
28
+ include_after(A, M)
29
+ end
30
+
31
+ B.ancestors #=> [B, A, M, ...]
32
+ B.swap_modules A, M
33
+ B.ancestors #=> [B, M, A, ...]
34
+ module J end
35
+ B.include_before A, J
36
+ B.ancestors #=> [B, M, J, A, ...]
37
+ B.remove_module M
38
+ B.ancestors #=> [B, J, A, ...]
39
+
40
+
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ $LOAD_PATH.unshift File.join(File.expand_path(__FILE__), '..')
2
+
3
+ require 'rake/clean'
4
+ require 'rake/gempackagetask'
5
+
6
+ require 'lib/remix/version'
7
+
8
+ $dlext = Config::CONFIG['DLEXT']
9
+
10
+ CLEAN.include("ext/**/*.#{$dlext}", "ext/**/*.log", "ext/**/*.o", "ext/**/*~", "ext/**/*#*", "ext/**/*.obj", "ext/**/*.def", "ext/**/*.pdb")
11
+ CLOBBER.include("**/*.#{$dlext}", "**/*~", "**/*#*", "**/*.log", "**/*.o")
12
+
13
+ specification = Gem::Specification.new do |s|
14
+ s.name = "remix"
15
+ s.summary = "Ruby modules re-mixed and remastered"
16
+ s.version = Remix::VERSION
17
+ s.date = Time.now.strftime '%Y-%m-%d'
18
+ s.author = "John Mair (banisterfiend)"
19
+ s.email = 'jrmair@gmail.com'
20
+ s.description = s.summary
21
+ s.require_path = 'lib'
22
+ s.platform = Gem::Platform::RUBY
23
+ #s.platform = 'i386-mswin32'
24
+ s.homepage = "http://banisterfiend.wordpress.com"
25
+ s.has_rdoc = 'yard'
26
+
27
+ s.extensions = ["ext/remix/extconf.rb"]
28
+ s.files = ["Rakefile", "README.markdown", "CHANGELOG",
29
+ "lib/remix.rb", "lib/remix/version.rb"] +
30
+ # ["lib/1.9/real_include.so", "lib/1.8/real_include.so"] +
31
+ FileList["ext/**/extconf.rb", "ext/**/*.h", "ext/**/*.c"].to_a
32
+ end
33
+
34
+ Rake::GemPackageTask.new(specification) do |package|
35
+ package.need_zip = false
36
+ package.need_tar = false
37
+ end
@@ -0,0 +1,57 @@
1
+ /* contains basic macros to facilitate ruby 1.8 and ruby 1.9 compatibility */
2
+
3
+ #ifndef GUARD_COMPAT_H
4
+ #define GUARD_COMPAT_H
5
+
6
+ #include <ruby.h>
7
+
8
+ /* test for 1.9 */
9
+ #if !defined(RUBY_19) && defined(ROBJECT_EMBED_LEN_MAX)
10
+ # define RUBY_19
11
+ #endif
12
+
13
+ /* macros for backwards compatibility with 1.8 */
14
+ #ifndef RUBY_19
15
+ # define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
16
+ # define RCLASS_SUPER(c) (RCLASS(c)->super)
17
+ # define RCLASS_IV_TBL(c) (RCLASS(c)->iv_tbl)
18
+ # define OBJ_UNTRUSTED OBJ_TAINTED
19
+ # include "st.h"
20
+ #endif
21
+
22
+ #ifdef RUBY_19
23
+ inline static VALUE
24
+ class_alloc(VALUE flags, VALUE klass)
25
+ {
26
+ rb_classext_t *ext = ALLOC(rb_classext_t);
27
+ NEWOBJ(obj, struct RClass);
28
+ OBJSETUP(obj, klass, flags);
29
+ obj->ptr = ext;
30
+ RCLASS_IV_TBL(obj) = 0;
31
+ RCLASS_M_TBL(obj) = 0;
32
+ RCLASS_SUPER(obj) = 0;
33
+ RCLASS_IV_INDEX_TBL(obj) = 0;
34
+ return (VALUE)obj;
35
+ }
36
+ #endif
37
+
38
+ inline static VALUE
39
+ create_class(VALUE flags, VALUE klass)
40
+ {
41
+ #ifdef RUBY_19
42
+ VALUE new_klass = class_alloc(flags, klass);
43
+ #else
44
+ NEWOBJ(new_klass, struct RClass);
45
+ OBJSETUP(new_klass, klass, flags);
46
+ #endif
47
+
48
+ return (VALUE)new_klass;
49
+ }
50
+
51
+ # define FALSE 0
52
+ # define TRUE 1
53
+
54
+ /* a useful macro. cannot use ordinary CLASS_OF as it does not return an lvalue */
55
+ #define KLASS_OF(c) (RBASIC(c)->klass)
56
+
57
+ #endif
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+
3
+ create_makefile('remix')
data/ext/remix/remix.c ADDED
@@ -0,0 +1,241 @@
1
+ /* object2module.c */
2
+ /* (C) John Mair 2009
3
+ * This program is distributed under the terms of the MIT License
4
+ * */
5
+
6
+ #include <ruby.h>
7
+ #include "compat.h"
8
+
9
+ /* a modified version of include_class_new from class.c */
10
+ static VALUE
11
+ j_class_new(VALUE module, VALUE sup)
12
+ {
13
+
14
+ VALUE klass = create_class(T_ICLASS, rb_cClass);
15
+
16
+ if (TYPE(module) == T_ICLASS) {
17
+ klass = module;
18
+ }
19
+
20
+ if (!RCLASS_IV_TBL(module)) {
21
+ RCLASS_IV_TBL(module) = (struct st_table *)st_init_numtable();
22
+ }
23
+
24
+ /* assign iv_tbl, m_tbl and super */
25
+ RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
26
+
27
+ if (TYPE(module) == T_ICLASS) {
28
+ if (!RTEST(rb_iv_get(module, "__module__")))
29
+ rb_iv_set(klass, "__module__", KLASS_OF(module));
30
+ }
31
+ else if (TYPE(module) == T_MODULE || TYPE(module) == T_CLASS)
32
+ rb_iv_set(klass, "__module__", module);
33
+
34
+ RCLASS_SUPER(klass) = sup;
35
+ if(TYPE(module) != T_OBJECT) {
36
+ RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
37
+ }
38
+ else {
39
+ RCLASS_M_TBL(klass) = RCLASS_M_TBL(CLASS_OF(module));
40
+ }
41
+
42
+ /* */
43
+
44
+ if (TYPE(module) == T_ICLASS) {
45
+ KLASS_OF(klass) = rb_iv_get(klass, "__module__");
46
+ }
47
+ else {
48
+ KLASS_OF(klass) = module;
49
+ }
50
+
51
+ if(TYPE(module) != T_OBJECT) {
52
+ OBJ_INFECT(klass, module);
53
+ OBJ_INFECT(klass, sup);
54
+ }
55
+
56
+ return (VALUE)klass;
57
+ }
58
+
59
+ static VALUE
60
+ set_supers(VALUE c)
61
+ {
62
+ if (RCLASS_SUPER(c) == rb_cObject || RCLASS_SUPER(c) == Qnil) {
63
+ return RCLASS_SUPER(c);
64
+ }
65
+ else {
66
+ return j_class_new(RCLASS_SUPER(c), set_supers(RCLASS_SUPER(c)));
67
+ }
68
+ }
69
+
70
+ VALUE
71
+ rb_prepare_for_remix(VALUE klass)
72
+ {
73
+ if (!RTEST(rb_obj_is_kind_of(klass, rb_cModule)))
74
+ rb_raise(rb_eTypeError, "Must be a Module or Class type.");
75
+
76
+ RCLASS_SUPER(klass) = set_supers(klass);
77
+
78
+ rb_clear_cache();
79
+ return klass;
80
+ }
81
+
82
+ inline static VALUE
83
+ get_source_module(VALUE mod)
84
+ {
85
+ switch (TYPE(mod)) {
86
+ case T_ICLASS:
87
+ if (RTEST(rb_iv_get(mod, "__module__")))
88
+ return rb_iv_get(mod, "__module__");
89
+ else
90
+ return KLASS_OF(mod);
91
+ break;
92
+ case T_CLASS:
93
+ case T_MODULE:
94
+ return mod;
95
+ break;
96
+ default:
97
+ rb_raise(rb_eRuntimeError, "get_source_module: mod is not a class or iclass!");
98
+ }
99
+
100
+ /* never reached */
101
+ return Qnil;
102
+ }
103
+
104
+ static VALUE
105
+ retrieve_before_mod(VALUE m, VALUE before)
106
+ {
107
+ VALUE k = get_source_module(RCLASS_SUPER(m));
108
+ while(k != before && m != Qnil && m != rb_cObject) {
109
+ m = RCLASS_SUPER(m);
110
+ k = get_source_module(RCLASS_SUPER(m));
111
+ }
112
+ if (get_source_module(RCLASS_SUPER(m)) != before)
113
+ rb_raise(rb_eRuntimeError, "'before' module not found");
114
+
115
+ return m;
116
+ }
117
+
118
+ static VALUE
119
+ retrieve_mod(VALUE m, VALUE after)
120
+ {
121
+ VALUE k = get_source_module(m);
122
+ while(k != after && m != Qnil && m != rb_cObject) {
123
+ m = RCLASS_SUPER(m);
124
+ k = get_source_module(m);
125
+ }
126
+
127
+ if (k != after)
128
+ rb_raise(rb_eRuntimeError, "'after' module not found");
129
+
130
+ return m;
131
+ }
132
+
133
+ VALUE
134
+ rb_include_after(VALUE self, VALUE after, VALUE mod)
135
+ {
136
+ rb_prepare_for_remix(self);
137
+
138
+ VALUE k, m = self;
139
+
140
+ k = get_source_module(m);
141
+ while(k != after && m != Qnil && m != rb_cObject) {
142
+ m = RCLASS_SUPER(m);
143
+ k = get_source_module(m);
144
+ }
145
+
146
+ if (k != after)
147
+ rb_raise(rb_eRuntimeError, "'after' module not found");
148
+
149
+ rb_include_module(m, mod);
150
+
151
+ return self;
152
+ }
153
+
154
+ VALUE
155
+ rb_include_before(VALUE self, VALUE before, VALUE mod)
156
+ {
157
+ rb_prepare_for_remix(self);
158
+
159
+ VALUE k, m = self;
160
+
161
+ k = get_source_module(RCLASS_SUPER(m));
162
+ while(k != before && m != Qnil && m != rb_cObject) {
163
+ m = RCLASS_SUPER(m);
164
+ k = get_source_module(RCLASS_SUPER(m));
165
+ }
166
+
167
+ if (get_source_module(RCLASS_SUPER(m)) != before)
168
+ rb_raise(rb_eRuntimeError, "'before' module not found");
169
+
170
+ rb_include_module(m, mod);
171
+
172
+ return self;
173
+ }
174
+
175
+ VALUE
176
+ rb_include_at(VALUE self, VALUE mod, VALUE rb_index)
177
+ {
178
+ rb_prepare_for_remix(self);
179
+
180
+ int index = FIX2INT(rb_index);
181
+ VALUE m = self;
182
+
183
+ int i = 0;
184
+ while(i++ < index && RCLASS_SUPER(m) != Qnil && RCLASS_SUPER(m) != rb_cObject)
185
+ m = RCLASS_SUPER(m);
186
+
187
+ rb_include_module(m, mod);
188
+ return self;
189
+ }
190
+
191
+ #define SWAP(X, Y) {(X) ^= (Y); (Y) ^= (X); (X) ^= (Y);}
192
+
193
+ VALUE
194
+ rb_swap_modules(VALUE self, VALUE mod1, VALUE mod2)
195
+ {
196
+ rb_prepare_for_remix(self);
197
+
198
+ VALUE before_mod1, before_mod2;
199
+ VALUE included_mod1, included_mod2;
200
+
201
+ if (mod1 == rb_cObject || mod2 == rb_cObject) rb_raise(rb_eRuntimeError, "can't swap Object");
202
+
203
+ included_mod1 = retrieve_mod(self, mod1);
204
+ included_mod2 = retrieve_mod(self, mod2);
205
+ before_mod1 = retrieve_before_mod(self, mod1);
206
+ before_mod2 = retrieve_before_mod(self, mod2);
207
+
208
+ SWAP(RCLASS_SUPER(before_mod1), RCLASS_SUPER(before_mod2));
209
+ SWAP(RCLASS_SUPER(included_mod1), RCLASS_SUPER(included_mod2));
210
+
211
+ rb_clear_cache();
212
+
213
+ return self;
214
+ }
215
+
216
+ VALUE
217
+ rb_remove_module(VALUE self, VALUE mod1)
218
+ {
219
+ rb_prepare_for_remix(self);
220
+
221
+ VALUE before = retrieve_before_mod(self, mod1);
222
+ VALUE included_mod = retrieve_mod(self, mod1);
223
+
224
+ if (mod1 == rb_cObject) rb_raise(rb_eRuntimeError, "can't delete Object");
225
+ RCLASS_SUPER(before) = RCLASS_SUPER(included_mod);
226
+ rb_clear_cache();
227
+
228
+ return self;
229
+ }
230
+
231
+ void
232
+ Init_remix()
233
+ {
234
+ rb_define_method(rb_cObject, "ready_remix", rb_prepare_for_remix, 0);
235
+ rb_define_method(rb_cModule, "include_at", rb_include_at, 2);
236
+ rb_define_method(rb_cModule, "include_before", rb_include_before, 2);
237
+ rb_define_method(rb_cModule, "include_after", rb_include_after, 2);
238
+ rb_define_method(rb_cModule, "swap_modules", rb_swap_modules, 2);
239
+ rb_define_method(rb_cModule, "remove_module", rb_remove_module, 1);
240
+ }
241
+
@@ -0,0 +1,3 @@
1
+ module Remix
2
+ VERSION = "0.1.0"
3
+ end
data/lib/remix.rb ADDED
@@ -0,0 +1,17 @@
1
+ direc = File.dirname(__FILE__)
2
+
3
+ require 'rbconfig'
4
+ require "#{direc}/remix/version"
5
+
6
+ dlext = Config::CONFIG['DLEXT']
7
+
8
+ begin
9
+ if RUBY_VERSION && RUBY_VERSION =~ /1.9/
10
+ require "#{direc}/1.9/remix.#{dlext}"
11
+ else
12
+ require "#{direc}/1.8/remix.#{dlext}"
13
+ end
14
+ rescue LoadError => e
15
+ require "#{direc}/remix.#{dlext}"
16
+ end
17
+
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: remix
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - John Mair (banisterfiend)
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-10-25 00:00:00 +13:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Ruby modules re-mixed and remastered
22
+ email: jrmair@gmail.com
23
+ executables: []
24
+
25
+ extensions:
26
+ - ext/remix/extconf.rb
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - Rakefile
31
+ - README.markdown
32
+ - CHANGELOG
33
+ - lib/remix.rb
34
+ - lib/remix/version.rb
35
+ - ext/remix/extconf.rb
36
+ - ext/remix/compat.h
37
+ - ext/remix/remix.c
38
+ has_rdoc: true
39
+ homepage: http://banisterfiend.wordpress.com
40
+ licenses: []
41
+
42
+ post_install_message:
43
+ rdoc_options: []
44
+
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ segments:
53
+ - 0
54
+ version: "0"
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ requirements: []
64
+
65
+ rubyforge_project:
66
+ rubygems_version: 1.3.7
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: Ruby modules re-mixed and remastered
70
+ test_files: []
71
+