texplay 0.2.7-x86-mswin32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/CHANGELOG +103 -0
  2. data/README.markdown +41 -0
  3. data/Rakefile +61 -0
  4. data/examples/common.rb +8 -0
  5. data/examples/example_alpha_blend.rb +31 -0
  6. data/examples/example_bezier.rb +42 -0
  7. data/examples/example_blur.rb +59 -0
  8. data/examples/example_color_control.rb +69 -0
  9. data/examples/example_color_transform.rb +29 -0
  10. data/examples/example_dup.rb +75 -0
  11. data/examples/example_each.rb +42 -0
  12. data/examples/example_effect.rb +35 -0
  13. data/examples/example_fill.rb +44 -0
  14. data/examples/example_fill_old.rb +49 -0
  15. data/examples/example_fluent.rb +31 -0
  16. data/examples/example_gen_eval.rb +34 -0
  17. data/examples/example_hash_arguments.rb +47 -0
  18. data/examples/example_lsystem.rb +61 -0
  19. data/examples/example_melt.rb +27 -0
  20. data/examples/example_polyline.rb +43 -0
  21. data/examples/example_scale.rb +29 -0
  22. data/examples/example_simple.rb +38 -0
  23. data/examples/example_splice.rb +33 -0
  24. data/examples/example_sync.rb +60 -0
  25. data/examples/example_turtle.rb +40 -0
  26. data/examples/media/empty2.png +0 -0
  27. data/examples/media/gosu.png +0 -0
  28. data/examples/media/logo.png +0 -0
  29. data/examples/media/maria.png +0 -0
  30. data/examples/media/rose.bmp +0 -0
  31. data/examples/media/sand1.png +0 -0
  32. data/examples/media/sunset.png +0 -0
  33. data/examples/media/texplay.png +0 -0
  34. data/ext/texplay/actions.c +1331 -0
  35. data/ext/texplay/actions.h +52 -0
  36. data/ext/texplay/bindings.c +1129 -0
  37. data/ext/texplay/bindings.h +46 -0
  38. data/ext/texplay/cache.c +135 -0
  39. data/ext/texplay/cache.h +24 -0
  40. data/ext/texplay/compat.h +27 -0
  41. data/ext/texplay/extconf.rb +30 -0
  42. data/ext/texplay/gen_eval.c +211 -0
  43. data/ext/texplay/gen_eval.h +20 -0
  44. data/ext/texplay/object2module.c +171 -0
  45. data/ext/texplay/object2module.h +11 -0
  46. data/ext/texplay/texplay.c +137 -0
  47. data/ext/texplay/texplay.h +107 -0
  48. data/ext/texplay/utils.c +978 -0
  49. data/ext/texplay/utils.h +145 -0
  50. data/lib/1.8/texplay.so +0 -0
  51. data/lib/1.9/texplay.so +0 -0
  52. data/lib/texplay-contrib.rb +171 -0
  53. data/lib/texplay.rb +134 -0
  54. metadata +114 -0
@@ -0,0 +1,46 @@
1
+ #ifndef GUARD_BINDINGS_H
2
+ #define GUARD_BINDINGS_H
3
+
4
+ /* class methods */
5
+ VALUE M_create_macro(VALUE self , VALUE method_name);
6
+ VALUE M_remove_macro(VALUE self, VALUE method_name);
7
+ VALUE M_refresh_cache_all(VALUE self);
8
+ VALUE M_create_blank(VALUE self, VALUE window, VALUE width, VALUE height);
9
+
10
+ /* instance methods */
11
+ VALUE m_paint(int argc, VALUE * argv, VALUE self);
12
+ VALUE m_getpixel(int argc, VALUE * argv, VALUE self);
13
+ VALUE m_circle(int argc, VALUE * argv, VALUE self);
14
+ VALUE m_line(int argc, VALUE * argv, VALUE self);
15
+ VALUE m_rect(int argc, VALUE * argv, VALUE self);
16
+ VALUE m_pixel(int argc, VALUE * argv, VALUE self);
17
+ VALUE m_flood_fill(int argc, VALUE * argv, VALUE self);
18
+ VALUE m_bezier(int argc, VALUE * argv, VALUE self);
19
+ VALUE m_polyline(int argc, VALUE * argv, VALUE self);
20
+ VALUE m_ngon(int argc, VALUE * argv, VALUE self);
21
+ VALUE m_special_pixel(int argc, VALUE * argv, VALUE self);
22
+ VALUE m_splice(int argc, VALUE * argv, VALUE self);
23
+ VALUE m_clear(int argc, VALUE * argv, VALUE self);
24
+ VALUE m_offset(int argc, VALUE * argv, VALUE self);
25
+ VALUE m_color(int argc, VALUE * argv, VALUE self);
26
+ VALUE m_missing(int argc, VALUE * argv, VALUE self);
27
+ VALUE m_bitmask(int argc, VALUE * argv, VALUE self);
28
+ VALUE m_lshift(int argc, VALUE * argv, VALUE self);
29
+ VALUE m_rshift(int argc, VALUE * argv, VALUE self);
30
+
31
+ VALUE m_each(int argc, VALUE * argv, VALUE self);
32
+
33
+ VALUE m_quad_cached(VALUE self);
34
+ VALUE m_cache_refresh(VALUE self);
35
+
36
+ VALUE m_user_set_options(VALUE self, VALUE options);
37
+ VALUE m_user_delete_options(VALUE self);
38
+ VALUE m_get_options(VALUE self);
39
+ VALUE m_force_sync(VALUE self, VALUE ary);
40
+
41
+ VALUE m_dup_image(VALUE self);
42
+ VALUE m_clone_image(VALUE self);
43
+
44
+ VALUE m_to_blob(VALUE self);
45
+
46
+ #endif
@@ -0,0 +1,135 @@
1
+ /* cache.c */
2
+
3
+ #include <ruby.h>
4
+
5
+ #ifdef __APPLE__
6
+ #include <glut.h>
7
+ #else
8
+ #include <GL/glut.h>
9
+ #endif
10
+
11
+ #include "cache.h"
12
+ #include "texplay.h"
13
+
14
+ typedef struct {
15
+ int len;
16
+ cache_entry entry[CACHE_SIZE];
17
+ } cache_t;
18
+
19
+ /* var has internal linkage, static duration */
20
+ /* contains cache data */
21
+ static cache_t cache = {0};
22
+
23
+ /* create a new cache entry */
24
+ cache_entry*
25
+ cache_create_entry(int tname) {
26
+ float * new_array;
27
+ int sidelength, new_element = cache.len;
28
+ GLint saved_tname;
29
+
30
+ if(cache.len >= CACHE_SIZE) { rb_raise(rb_eRuntimeError, "cache is full! increase CACHE_SIZE"); }
31
+
32
+ /* save current texture binding */
33
+ /* glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_tname); */
34
+
35
+ /* opengl initialization code */
36
+ glEnable(GL_TEXTURE_2D);
37
+ glBindTexture(GL_TEXTURE_2D, tname);
38
+
39
+ /* get length of a side, since square texture */
40
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &sidelength);
41
+
42
+ /* initialize texture data array, mult. by 4 because {rgba} */
43
+ new_array = malloc(sidelength * sidelength * 4 * sizeof(float));
44
+
45
+ /* get texture data from video memory */
46
+ glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT,(void*)(new_array));
47
+
48
+ /* save texture data in the cache */
49
+ cache.entry[new_element].tname = tname;
50
+ cache.entry[new_element].sidelength = sidelength;
51
+ cache.entry[new_element].tdata = new_array;
52
+
53
+ /* update size of cache */
54
+ cache.len++;
55
+
56
+ /* restore saved texture binding */
57
+ /* glBindTexture(GL_TEXTURE_2D, saved_tname); */
58
+
59
+ glDisable(GL_TEXTURE_2D);
60
+
61
+
62
+ return &cache.entry[new_element];
63
+ }
64
+
65
+ /* return the entry if it exists, otherwise return NULL */
66
+ cache_entry*
67
+ find_in_cache(int tname) {
68
+ /* check if entry exists in cache */
69
+ int index;
70
+ for(index = 0; index < cache.len; index++)
71
+ if(cache.entry[index].tname == tname)
72
+ return &cache.entry[index];
73
+
74
+
75
+ return NULL;
76
+ }
77
+
78
+ /* if the entry doesn't exist then create it and return it.
79
+ otherwise just return it */
80
+ cache_entry*
81
+ find_or_create_cache_entry(int tname) {
82
+ cache_entry * entry;
83
+
84
+ if((entry=find_in_cache(tname)))
85
+ return entry;
86
+ else
87
+ return cache_create_entry(tname);
88
+ }
89
+
90
+ /* refresh the cache for all quads */
91
+ void
92
+ cache_refresh_all(void) {
93
+ float * tdata;
94
+ int tname, index;
95
+ GLint saved_tname;
96
+
97
+ /* save current texture binding */
98
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_tname);
99
+
100
+ for(index = 0; index < cache.len; index++) {
101
+ tdata = cache.entry[index].tdata;
102
+ tname = cache.entry[index].tname;
103
+
104
+ /* opengl initialization code */
105
+ glEnable(GL_TEXTURE_2D);
106
+ glBindTexture(GL_TEXTURE_2D, tname);
107
+
108
+ glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, (void*)(tdata));
109
+ }
110
+
111
+ /* restore saved texture binding */
112
+ glBindTexture(GL_TEXTURE_2D, saved_tname);
113
+ }
114
+
115
+ /* refresh the cache for a specific quad */
116
+ void
117
+ cache_refresh_entry(int tname) {
118
+ GLint saved_tname;
119
+ cache_entry * entry;
120
+
121
+ /* save current texture binding */
122
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_tname);
123
+
124
+ entry = find_in_cache(tname);
125
+
126
+ /* opengl initialization code */
127
+ glEnable(GL_TEXTURE_2D);
128
+ glBindTexture(GL_TEXTURE_2D, entry->tname);
129
+
130
+ glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, (void*)(entry->tdata));
131
+
132
+ /* restore saved texture binding */
133
+ glBindTexture(GL_TEXTURE_2D, saved_tname);
134
+ }
135
+
@@ -0,0 +1,24 @@
1
+ /* cache.h */
2
+ /* see cache.c for annotations */
3
+
4
+ #ifndef GUARD_CACHE_H
5
+ #define GUARD_CACHE_H
6
+
7
+ /* defines */
8
+ #define CACHE_SIZE 10000
9
+
10
+ /* data types */
11
+ typedef struct {
12
+ int tname;
13
+ int sidelength;
14
+ float * tdata;
15
+ } cache_entry;
16
+
17
+ /* functions */
18
+ void cache_refresh_all(void);
19
+ void cache_refresh_entry(int tname);
20
+ cache_entry * cache_create_entry(int texture_name);
21
+ cache_entry * find_in_cache(int texture_name);
22
+ cache_entry * find_or_create_cache_entry(int texture_name);
23
+
24
+ #endif
@@ -0,0 +1,27 @@
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
+ /* this is the test we use to identify ruby 1.9.1 */
9
+
10
+ /* commenting out this test because it doesn't seem to work in 1.8.7 */
11
+ /*
12
+ #ifdef RCLASS_M_TBL
13
+ # define RUBY_19
14
+ #endif
15
+ */
16
+
17
+ /* macros for backwards compatibility with 1.8 */
18
+ #ifndef RUBY_19
19
+ # define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
20
+ # define RCLASS_SUPER(c) (RCLASS(c)->super)
21
+ # define RCLASS_IV_TBL(c) (RCLASS(c)->iv_tbl)
22
+ #endif
23
+
24
+ /* a useful macro. cannot use ordinary CLASS_OF as it does not return an lvalue */
25
+ #define KLASS_OF(c) (RBASIC(c)->klass)
26
+
27
+ #endif
@@ -0,0 +1,30 @@
1
+ require 'mkmf'
2
+
3
+
4
+ # linux
5
+ if RUBY_PLATFORM =~ /linux/ then
6
+ exit unless have_library("glut")
7
+ exit unless have_library("GL")
8
+
9
+ # macosx
10
+ elsif RUBY_PLATFORM =~ /darwin/
11
+ $LDFLAGS += " -framework GLUT"
12
+ $CFLAGS += " -I/System/Library/Frameworks/GLUT.framework/Headers"
13
+
14
+ # windows
15
+ else
16
+
17
+ exit unless have_library("freeglut_static")
18
+ exit unless have_library("opengl32")
19
+
20
+ if RUBY_PLATFORM =~ /mingw/
21
+ $CFLAGS += " -I/home/john/.rake-compiler/ruby/ruby-1.9.1-p243/include"
22
+ $CFLAGS += " -I/home/john/.rake-compiler/ruby/ruby-1.8.6-p287/include"
23
+ $CFLAGS += " -D FREEGLUT_STATIC"
24
+ end
25
+ end
26
+
27
+ # 1.9 compatibility
28
+ $CFLAGS += " -DRUBY_19" if RUBY_VERSION =~ /1.9/
29
+
30
+ create_makefile('texplay')
@@ -0,0 +1,211 @@
1
+ /* gen_eval.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 "object2module.h"
8
+ #include "compat.h"
9
+
10
+ VALUE
11
+ retrieve_hidden_self(VALUE duped_context)
12
+ {
13
+ VALUE thread_id, unique_name, hidden_self;
14
+
15
+ /* retrieve hidden self (if it exists) */
16
+ thread_id = rb_funcall(rb_obj_id(rb_thread_current()), rb_intern("to_s"), 0);
17
+ unique_name = rb_str_plus(rb_str_new2("__hidden_self__"), thread_id);
18
+
19
+ hidden_self = rb_ivar_get(duped_context, rb_to_id(unique_name));
20
+
21
+ return hidden_self;
22
+ }
23
+
24
+ void
25
+ set_hidden_self(VALUE duped_context, VALUE hidden_self)
26
+ {
27
+ VALUE thread_id, unique_name;
28
+
29
+ /* generate a unique (thread safe) name for the hidden self */
30
+ thread_id = rb_funcall(rb_obj_id(rb_thread_current()), rb_intern("to_s"), 0);
31
+ unique_name = rb_str_plus(rb_str_new2("__hidden_self__"), thread_id);
32
+
33
+ /* store self in hidden var in duped context */
34
+ rb_ivar_set(duped_context, rb_to_id(unique_name), hidden_self);
35
+ }
36
+
37
+ VALUE
38
+ rb_capture(VALUE self) {
39
+ VALUE hidden_self;
40
+ VALUE result;
41
+
42
+ rb_need_block();
43
+
44
+ hidden_self = retrieve_hidden_self(self);
45
+
46
+ /* 2 cases: (1) if rb_gen_eval is active then instance_eval wrt hidden_self
47
+ (2) otherwise simply yield to the block
48
+ */
49
+ if(!NIL_P(hidden_self))
50
+ result = rb_obj_instance_eval(0, 0, hidden_self);
51
+ else
52
+ result = rb_yield(Qnil);
53
+
54
+ /* we want the return value of capture to be the return value of the block */
55
+ return result;
56
+ }
57
+
58
+ /** ruby 1.9 funcs **/
59
+ #ifdef RUBY_19
60
+ void
61
+ redirect_iv_for_object(VALUE obj, VALUE dest)
62
+ {
63
+ if(TYPE(obj) != T_OBJECT)
64
+ rb_raise(rb_eArgError, "must provide a T_OBJECT");
65
+
66
+ if (!(RBASIC(dest)->flags & ROBJECT_EMBED) && ROBJECT_IVPTR(dest)) {
67
+ rb_raise(rb_eArgError, "im sorry gen_eval does not yet work with this type of ROBJECT");
68
+ }
69
+ if (RBASIC(obj)->flags & ROBJECT_EMBED) {
70
+ rb_raise(rb_eArgError, "im sorry gen_eval does not yet work with ROBJECT_EMBED types");
71
+ }
72
+ else {
73
+ ROBJECT(dest)->as.heap.ivptr = ROBJECT(obj)->as.heap.ivptr;
74
+ ROBJECT(dest)->as.heap.numiv = ROBJECT(obj)->as.heap.numiv;
75
+ ROBJECT(dest)->as.heap.iv_index_tbl = ROBJECT(obj)->as.heap.iv_index_tbl;
76
+ RBASIC(dest)->flags &= ~ROBJECT_EMBED;
77
+ }
78
+ }
79
+
80
+ void
81
+ release_iv_for_object(VALUE obj)
82
+ {
83
+ if(TYPE(obj) != T_OBJECT)
84
+ rb_raise(rb_eArgError, "must provide a T_OBJECT");
85
+
86
+ ROBJECT(obj)->as.heap.ivptr = (void *) 0;
87
+ ROBJECT(obj)->as.heap.numiv = 0;
88
+ ROBJECT(obj)->as.heap.iv_index_tbl = (void *) 0;
89
+ RBASIC(obj)->flags &= ~ROBJECT_EMBED;
90
+ }
91
+ #endif
92
+ /** end of ruby 1.9 funcs **/
93
+
94
+ VALUE
95
+ rb_gen_eval(int argc, VALUE * argv, VALUE self) {
96
+ VALUE duped_context;
97
+ VALUE is_a_module;
98
+ VALUE context;
99
+ VALUE result;
100
+
101
+ rb_need_block();
102
+
103
+ context = rb_funcall(rb_block_proc(), rb_intern("__context__"), 0);
104
+
105
+ /* using Class instead of Object (where possible) because Object's iv_tbl setup in 1.9 is weird */
106
+ #ifdef RUBY_19
107
+ if(TYPE(context) == T_OBJECT)
108
+ duped_context = rb_funcall(rb_cObject, rb_intern("new"), 0);
109
+ else
110
+ duped_context = rb_funcall(rb_cClass, rb_intern("new"), 0);
111
+
112
+ #else
113
+
114
+ duped_context = rb_funcall(rb_cClass, rb_intern("new"), 0);
115
+
116
+ #endif
117
+
118
+
119
+ /* the duped_context shares the context's iv_tbl.
120
+ 2 cases: (1) external iv_tbl, (2) local iv_tbl
121
+
122
+ NOTE: we do not need to save original iv_tbl before replacing it, a brand new Class
123
+ instance does not yet have an iv_tbl (the pointer is set to 0)
124
+ */
125
+ if(FL_TEST(context, FL_EXIVAR))
126
+ RCLASS_IV_TBL(duped_context) = (struct st_table *) rb_generic_ivar_table(context);
127
+ else {
128
+ #ifdef RUBY_19
129
+ if(TYPE(context) == T_OBJECT)
130
+ redirect_iv_for_object(context, duped_context);
131
+ else {
132
+ RCLASS_IV_TBL(duped_context) = (struct st_table *) RCLASS_IV_TBL(context);
133
+ }
134
+ #else
135
+ RCLASS_IV_TBL(duped_context) = (struct st_table *) RCLASS_IV_TBL(context);
136
+ #endif
137
+
138
+
139
+ }
140
+
141
+ /* ensure singleton exists */
142
+ rb_singleton_class(context);
143
+
144
+ /* set up the class hierarchy for our dup_context */
145
+ KLASS_OF(duped_context) = rb_singleton_class_clone(context);
146
+
147
+ /* if no args then default to mixing in 'self' */
148
+ if(argc == 0) {
149
+ argc = 1;
150
+ argv = &self;
151
+ }
152
+
153
+ /* mix the objects (or self) into the duped context */
154
+ rb_gen_extend(argc, argv, duped_context);
155
+
156
+ /* store self in hidden var in duped context */
157
+ set_hidden_self(duped_context, self);
158
+
159
+ is_a_module = rb_funcall(duped_context, rb_intern("is_a?"), 1, rb_cModule);
160
+
161
+ /* eval block wrt duped_context */
162
+ if(is_a_module == Qtrue)
163
+ result = rb_mod_module_eval(0, 0, duped_context);
164
+ else
165
+ result = rb_obj_instance_eval(0, 0, duped_context);
166
+
167
+ /* clean up goes below */
168
+
169
+ /* release context's iv_tbl from duped_context. */
170
+ #ifdef RUBY_19
171
+ if(TYPE(duped_context) == T_OBJECT)
172
+ release_iv_for_object(duped_context);
173
+ else {
174
+ RCLASS_IV_TBL(duped_context) = (struct st_table *) 0;
175
+ }
176
+ #else
177
+ RCLASS_IV_TBL(duped_context) = (struct st_table *) 0;
178
+ #endif
179
+
180
+ /* delete hidden self */
181
+ set_hidden_self(duped_context, Qnil);
182
+
183
+ return result;
184
+ }
185
+
186
+ void
187
+ Init_gen_eval() {
188
+
189
+ rb_define_method(rb_cObject, "gen_eval", rb_gen_eval, -1);
190
+ rb_define_method(rb_cObject, "capture", rb_capture, 0);
191
+
192
+ rb_define_method(rb_cObject, "to_module", rb_to_module , 0);
193
+ rb_define_method(rb_cObject, "reset_tbls", rb_reset_tbls , 0);
194
+ rb_define_method(rb_cObject, "gen_extend", rb_gen_extend, -1);
195
+ rb_define_method(rb_cModule, "gen_include", rb_gen_include, -1);
196
+
197
+ /* below is much too hard to achieve in pure C */
198
+ rb_eval_string("class Proc;"
199
+ " def __context__;"
200
+ " eval('self', self.binding);"
201
+ " end;"
202
+ "end;"
203
+ );
204
+
205
+ rb_define_alias(rb_cObject, "gen_eval_with", "gen_eval");
206
+ }
207
+
208
+
209
+
210
+
211
+
@@ -0,0 +1,20 @@
1
+ /* gen_eval.h */
2
+
3
+ #ifndef GUARD_GEN_EVAL_H
4
+ #define GUARD_GEN_EVAL_H
5
+
6
+ #include <ruby.h>
7
+
8
+ VALUE rb_gen_eval(int argc, VALUE * argv, VALUE self);
9
+ VALUE rb_capture(VALUE self);
10
+ VALUE retrieve_hidden_self(VALUE duped_context);
11
+ void set_hidden_self(VALUE duped_context, VALUE hidden_self);
12
+
13
+ /* change self to hidden self if __hidden_self__ defined */
14
+ #define ADJUST_SELF(X) \
15
+ do { \
16
+ if(!NIL_P(retrieve_hidden_self((X)))) \
17
+ (X) = retrieve_hidden_self((X)); \
18
+ } while(0)
19
+
20
+ #endif
@@ -0,0 +1,171 @@
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
+ #ifdef RUBY_19
10
+ # include <ruby/st.h>
11
+ #else
12
+ # include <st.h>
13
+ #endif
14
+
15
+ /* class creation. from class.c in 1.9.1 */
16
+ #ifdef RUBY_19
17
+ static VALUE
18
+ class_alloc(VALUE flags, VALUE klass)
19
+ {
20
+ rb_classext_t *ext = ALLOC(rb_classext_t);
21
+ NEWOBJ(obj, struct RClass);
22
+ OBJSETUP(obj, klass, flags);
23
+ obj->ptr = ext;
24
+ RCLASS_IV_TBL(obj) = 0;
25
+ RCLASS_M_TBL(obj) = 0;
26
+ RCLASS_SUPER(obj) = 0;
27
+ RCLASS_IV_INDEX_TBL(obj) = 0;
28
+ return (VALUE)obj;
29
+ }
30
+ #endif
31
+
32
+ /* a modified version of include_class_new from class.c */
33
+ static VALUE
34
+ j_class_new(VALUE module, VALUE sup)
35
+ {
36
+
37
+ #ifdef RUBY_19
38
+ VALUE klass = class_alloc(T_ICLASS, rb_cClass);
39
+ #else
40
+ NEWOBJ(klass, struct RClass);
41
+ OBJSETUP(klass, rb_cClass, T_ICLASS);
42
+ #endif
43
+
44
+ if (BUILTIN_TYPE(module) == T_ICLASS) {
45
+ module = KLASS_OF(module);
46
+ }
47
+
48
+ if (!RCLASS_IV_TBL(module)) {
49
+
50
+ RCLASS_IV_TBL(module) = (struct st_table *)st_init_numtable();
51
+ }
52
+
53
+ /* assign iv_tbl, m_tbl and super */
54
+ RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
55
+ RCLASS_SUPER(klass) = sup;
56
+ if(TYPE(module) != T_OBJECT) {
57
+
58
+ RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
59
+ }
60
+ else {
61
+ RCLASS_M_TBL(klass) = RCLASS_M_TBL(CLASS_OF(module));
62
+ }
63
+
64
+ /* */
65
+
66
+ if (TYPE(module) == T_ICLASS) {
67
+ KLASS_OF(klass) = KLASS_OF(module);
68
+ }
69
+ else {
70
+ KLASS_OF(klass) = module;
71
+ }
72
+
73
+ if(TYPE(module) != T_OBJECT) {
74
+ OBJ_INFECT(klass, module);
75
+ OBJ_INFECT(klass, sup);
76
+ }
77
+ return (VALUE)klass;
78
+ }
79
+
80
+ VALUE
81
+ rb_to_module(VALUE self)
82
+ {
83
+ VALUE rclass, chain_start, jcur, klass;
84
+
85
+ switch(BUILTIN_TYPE(self)) {
86
+ case T_MODULE:
87
+ return self;
88
+ case T_CLASS:
89
+ klass = self;
90
+ break;
91
+ case T_OBJECT:
92
+ default:
93
+ klass = rb_singleton_class(self);
94
+ }
95
+
96
+ chain_start = j_class_new(klass, rb_cObject);
97
+
98
+ KLASS_OF(chain_start) = rb_cModule;
99
+ RBASIC(chain_start)->flags = T_MODULE;
100
+
101
+ jcur = chain_start;
102
+ for(rclass = RCLASS_SUPER(klass); rclass != rb_cObject;
103
+ rclass = RCLASS_SUPER(rclass)) {
104
+
105
+ RCLASS_SUPER(jcur) = j_class_new(rclass, rb_cObject);
106
+ jcur = RCLASS_SUPER(jcur);
107
+ }
108
+
109
+ RCLASS_SUPER(jcur) = (VALUE)NULL;
110
+
111
+ return chain_start;
112
+ }
113
+
114
+ VALUE
115
+ rb_reset_tbls(VALUE self)
116
+ {
117
+ RCLASS_IV_TBL(self) = (struct st_table *) 0;
118
+ RCLASS_M_TBL(self) = (struct st_table *) st_init_numtable();
119
+ return Qnil;
120
+ }
121
+
122
+ /* cannot simply forward to gen_include as need to invoke 'extended' hook */
123
+ VALUE
124
+ rb_gen_extend(int argc, VALUE * argv, VALUE self)
125
+ {
126
+ int i;
127
+
128
+ if (argc == 0) rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
129
+
130
+ rb_singleton_class(self);
131
+
132
+ for(i = 0; i < argc; i++) {
133
+ VALUE mod = rb_to_module(argv[i]);
134
+ rb_funcall(mod, rb_intern("extend_object"), 1, self);
135
+ rb_funcall(mod, rb_intern("extended"), 1, self);
136
+
137
+ /* only redirect if argv[i] is not a module */
138
+ if(argv[i] != mod) rb_reset_tbls(mod);
139
+ }
140
+
141
+ return self;
142
+ }
143
+
144
+ VALUE
145
+ rb_gen_include(int argc, VALUE * argv, VALUE self)
146
+ {
147
+ int i;
148
+
149
+ if (argc == 0) rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
150
+
151
+ for(i = 0; i < argc; i++) {
152
+ VALUE mod = rb_to_module(argv[i]);
153
+ rb_funcall(mod, rb_intern("append_features"), 1, self);
154
+ rb_funcall(mod, rb_intern("included"), 1, self);
155
+
156
+ if(argv[i] != mod) rb_reset_tbls(mod);
157
+ }
158
+
159
+ return self;
160
+ }
161
+
162
+
163
+ void Init_object2module()
164
+ {
165
+
166
+ rb_define_method(rb_cObject, "to_module", rb_to_module , 0);
167
+ rb_define_method(rb_cObject, "gen_extend", rb_gen_extend, -1);
168
+ rb_define_method(rb_cModule, "gen_include", rb_gen_include, -1);
169
+ rb_define_method(rb_cModule, "reset_tbls", rb_reset_tbls, 0);
170
+ }
171
+
@@ -0,0 +1,11 @@
1
+ /* object2module.h */
2
+
3
+ #ifndef GUARD_OBJECT2MODULE_H
4
+ #define GUARD_OBJECT2MODULE_H
5
+
6
+ VALUE rb_gen_include(int argc, VALUE * argv, VALUE self);
7
+ VALUE rb_gen_extend(int argc, VALUE * argv, VALUE self);
8
+ VALUE rb_to_module(VALUE self);
9
+ VALUE rb_reset_tbls(VALUE self);
10
+
11
+ #endif