object2module 0.1.0 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +14 -0
- data/README.markdown +11 -0
- data/lib/object2module.rb +103 -12
- data/test/test_object2module.rb +114 -114
- metadata +25 -22
- data/README.rdoc +0 -18
- data/Rakefile +0 -84
- data/ext/compat.h +0 -18
- data/ext/extconf.rb +0 -6
- data/ext/object2module.c +0 -215
- data/ext/object2module.h +0 -11
data/LICENSE
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Copyright (c) 2008 John Mair
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the
|
4
|
+
"Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
5
|
+
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
|
6
|
+
conditions:
|
7
|
+
|
8
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
9
|
+
|
10
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
11
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
12
|
+
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
13
|
+
OR OTHER DEALINGS IN THE SOFTWARE.
|
14
|
+
|
data/README.markdown
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
Object2module
|
2
|
+
=============
|
3
|
+
|
4
|
+
* converts a Class (or the Singleton of an Object) to a Module
|
5
|
+
* Includes gen\_extend and gen\_include methods: generalizations of Object#extend and Module#include that work with
|
6
|
+
Objects and Classes as well as Modules
|
7
|
+
|
8
|
+
How it works:
|
9
|
+
* First creates an IClass for the Class in question and sets the T\_MODULE flag
|
10
|
+
* Recursively coverts superclasses of the Class to IClasses creating a modulified version of the Class's inheritance chain
|
11
|
+
* gen\_include/gen\_extend automatically call #object2module on the Class/Object before inclusion/extension.
|
data/lib/object2module.rb
CHANGED
@@ -1,13 +1,104 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
1
|
+
require 'rubygems'
|
2
|
+
require 'inline'
|
3
|
+
|
4
|
+
|
5
|
+
module Object2module
|
6
|
+
VERSION = "0.1.0"
|
7
|
+
end
|
8
|
+
|
9
|
+
class Object
|
10
|
+
inline do |builder|
|
11
|
+
builder.prefix %{
|
12
|
+
#define KLASS_OF(o) RCLASS(RBASIC(o)->klass)
|
13
|
+
#define SUPER(o) RCLASS(o)->super
|
14
|
+
|
15
|
+
VALUE
|
16
|
+
j_class_new(VALUE module, VALUE sup) {
|
17
|
+
|
18
|
+
|
19
|
+
NEWOBJ(klass, struct RClass);
|
20
|
+
OBJSETUP(klass, rb_cClass, T_ICLASS);
|
21
|
+
|
22
|
+
if (BUILTIN_TYPE(module) == T_ICLASS) {
|
23
|
+
module = RBASIC(module)->klass;
|
24
|
+
}
|
25
|
+
|
26
|
+
if (!RCLASS(module)->iv_tbl) {
|
27
|
+
|
28
|
+
RCLASS(module)->iv_tbl = (struct st_table *)st_init_numtable();
|
29
|
+
}
|
30
|
+
|
31
|
+
/* assign iv_tbl, m_tbl and super */
|
32
|
+
klass->iv_tbl = RCLASS(module)->iv_tbl;
|
33
|
+
klass->super = sup;
|
34
|
+
if(TYPE(module) != T_OBJECT) {
|
35
|
+
|
36
|
+
klass->m_tbl = RCLASS(module)->m_tbl;
|
37
|
+
}
|
38
|
+
else {
|
39
|
+
klass->m_tbl = RCLASS(CLASS_OF(module))->m_tbl;
|
40
|
+
}
|
41
|
+
|
42
|
+
/* */
|
43
|
+
|
44
|
+
if (TYPE(module) == T_ICLASS) {
|
45
|
+
RBASIC(klass)->klass = RBASIC(module)->klass;
|
46
|
+
}
|
47
|
+
else {
|
48
|
+
RBASIC(klass)->klass = module;
|
49
|
+
}
|
50
|
+
|
51
|
+
|
52
|
+
if(TYPE(module) != T_OBJECT) {
|
53
|
+
OBJ_INFECT(klass, module);
|
54
|
+
OBJ_INFECT(klass, sup);
|
55
|
+
}
|
56
|
+
return (VALUE)klass;
|
57
|
+
}
|
58
|
+
|
59
|
+
|
60
|
+
}
|
61
|
+
|
62
|
+
builder.c %{
|
63
|
+
VALUE
|
64
|
+
object2module() {
|
65
|
+
VALUE rclass, chain_start, jcur, klass;
|
66
|
+
|
67
|
+
if(BUILTIN_TYPE(self) == T_CLASS)
|
68
|
+
klass = self;
|
69
|
+
else if(BUILTIN_TYPE(self) == T_OBJECT)
|
70
|
+
klass = rb_singleton_class(self);
|
71
|
+
else if(BUILTIN_TYPE(self) == T_MODULE)
|
72
|
+
return self;
|
73
|
+
else
|
74
|
+
return Qnil;
|
75
|
+
|
76
|
+
chain_start = j_class_new(klass, rb_cObject);
|
77
|
+
|
78
|
+
RBASIC(chain_start)->klass = rb_cModule;
|
79
|
+
RBASIC(chain_start)->flags = T_MODULE;
|
80
|
+
|
81
|
+
jcur = chain_start;
|
82
|
+
for(rclass = SUPER(klass); rclass != rb_cObject; rclass = SUPER(rclass)) {
|
83
|
+
RCLASS(jcur)->super = j_class_new(rclass, rb_cObject);
|
84
|
+
jcur = SUPER(jcur);
|
85
|
+
}
|
86
|
+
|
87
|
+
SUPER(jcur) = (VALUE)NULL;
|
88
|
+
|
89
|
+
return chain_start;
|
90
|
+
}
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
def gen_extend(*objs)
|
95
|
+
extend(*objs.map { |o| o.object2module })
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
class Module
|
101
|
+
def gen_include(*objs)
|
102
|
+
include(*objs.map { |o| o.object2module })
|
103
|
+
end
|
13
104
|
end
|
data/test/test_object2module.rb
CHANGED
@@ -1,30 +1,30 @@
|
|
1
1
|
require 'test/unit'
|
2
|
-
require 'object2module'
|
2
|
+
require '../lib/object2module'
|
3
3
|
|
4
4
|
module M
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
def m
|
6
|
+
"m"
|
7
|
+
end
|
8
8
|
end
|
9
9
|
|
10
10
|
class A
|
11
|
-
|
11
|
+
include M
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
def a
|
14
|
+
"a"
|
15
|
+
end
|
16
16
|
end
|
17
17
|
|
18
18
|
class B < A
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
def b
|
20
|
+
"b"
|
21
|
+
end
|
22
22
|
end
|
23
23
|
|
24
24
|
class C < B
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
def c
|
26
|
+
"c"
|
27
|
+
end
|
28
28
|
end
|
29
29
|
|
30
30
|
# stand-alone class
|
@@ -42,104 +42,104 @@ class J
|
|
42
42
|
end
|
43
43
|
|
44
44
|
class Object2ModuleTest < Test::Unit::TestCase
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
45
|
+
def test_class_to_module
|
46
|
+
assert_instance_of(Module, C.object2module)
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_class_heirarchy
|
50
|
+
h = C.object2module.ancestors
|
51
|
+
assert_equal(B, h[1])
|
52
|
+
assert_equal(A, h[2])
|
53
|
+
assert_equal(M, h[3])
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_class_extend
|
57
|
+
h = C.object2module
|
58
|
+
o = Object.new
|
59
|
+
assert_equal(o, o.extend(h))
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_class_extended_methods
|
63
|
+
h = C.object2module
|
64
|
+
o = Object.new
|
65
|
+
o.extend(h)
|
66
|
+
assert_equal("a", o.a)
|
67
|
+
assert_equal("b", o.b)
|
68
|
+
assert_equal("c", o.c)
|
69
|
+
assert_equal("m", o.m)
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_object_to_module
|
73
|
+
o = C.new
|
74
|
+
assert_instance_of(Module, o.object2module)
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_object_heirarchy
|
79
|
+
o = C.new
|
80
|
+
h = o.object2module.ancestors
|
81
|
+
assert_equal(C, h[1])
|
82
|
+
assert_equal(B, h[2])
|
83
|
+
assert_equal(A, h[3])
|
84
|
+
assert_equal(M, h[4])
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_object_extend
|
88
|
+
h = C.object2module
|
89
|
+
o = Object.new
|
90
|
+
assert_equal(o, o.extend(h))
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_object_extended_methods
|
94
|
+
o = C.new
|
95
|
+
h = o.object2module
|
96
|
+
l = Object.new
|
97
|
+
l.extend(h)
|
98
|
+
assert_equal("a", l.a)
|
99
|
+
assert_equal("b", l.b)
|
100
|
+
assert_equal("c", l.c)
|
101
|
+
assert_equal("m", l.m)
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_gen_extend
|
105
|
+
o = Object.new
|
106
|
+
o.gen_extend(C)
|
107
|
+
assert_equal("a", o.a)
|
108
|
+
assert_equal("b", o.b)
|
109
|
+
assert_equal("c", o.c)
|
110
|
+
assert_equal("m", o.m)
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_gen_include
|
114
|
+
k = Class.new
|
115
|
+
k.gen_include(C)
|
116
|
+
o = k.new
|
117
|
+
assert_equal("a", o.a)
|
118
|
+
assert_equal("b", o.b)
|
119
|
+
assert_equal("c", o.c)
|
120
|
+
assert_equal("m", o.m)
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_gen_extend_multi
|
124
|
+
o = Object.new
|
125
|
+
o.gen_extend(C, K, J)
|
126
|
+
assert_equal("a", o.a)
|
127
|
+
assert_equal("b", o.b)
|
128
|
+
assert_equal("c", o.c)
|
129
|
+
assert_equal("m", o.m)
|
130
|
+
assert_equal("k", o.k)
|
131
|
+
assert_equal("j", o.j)
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_gen_include_multi
|
135
|
+
k = Class.new
|
136
|
+
k.gen_include(C, K, J)
|
137
|
+
o = k.new
|
138
|
+
assert_equal("a", o.a)
|
139
|
+
assert_equal("b", o.b)
|
140
|
+
assert_equal("c", o.c)
|
141
|
+
assert_equal("m", o.m)
|
142
|
+
assert_equal("k", o.k)
|
143
|
+
assert_equal("j", o.j)
|
144
|
+
end
|
145
145
|
end
|
metadata
CHANGED
@@ -1,42 +1,45 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: object2module
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- John Mair
|
7
|
+
- John Mair
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2008-12-17 00:00:00 +13:00
|
13
13
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
16
|
-
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: RubyInline
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 3.6.7
|
24
|
+
version:
|
25
|
+
description: Convert Classes and Objects to Modules so they can be extended/included.
|
17
26
|
email: jrmair@gmail.com
|
18
27
|
executables: []
|
19
28
|
|
20
|
-
extensions:
|
21
|
-
|
22
|
-
extra_rdoc_files:
|
23
|
-
|
24
|
-
- ext/object2module.c
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files: []
|
32
|
+
|
25
33
|
files:
|
26
|
-
-
|
34
|
+
- README.markdown
|
35
|
+
- LICENSE
|
27
36
|
- lib/object2module.rb
|
28
|
-
- README.rdoc
|
29
|
-
- ext/object2module.c
|
30
|
-
- ext/object2module.h
|
31
|
-
- ext/compat.h
|
32
|
-
- ext/extconf.rb
|
33
37
|
- test/test_object2module.rb
|
34
|
-
has_rdoc:
|
38
|
+
has_rdoc: false
|
35
39
|
homepage: http://banisterfiend.wordpress.com
|
36
40
|
post_install_message:
|
37
|
-
rdoc_options:
|
38
|
-
|
39
|
-
- README.rdoc
|
41
|
+
rdoc_options: []
|
42
|
+
|
40
43
|
require_paths:
|
41
44
|
- lib
|
42
45
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -57,6 +60,6 @@ rubyforge_project:
|
|
57
60
|
rubygems_version: 1.2.0
|
58
61
|
signing_key:
|
59
62
|
specification_version: 2
|
60
|
-
summary:
|
63
|
+
summary: Convert Classes and Objects to Modules so they can be extended/included.
|
61
64
|
test_files: []
|
62
65
|
|
data/README.rdoc
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
# Object2module
|
2
|
-
|
3
|
-
- converts a Class (or the Singleton of an Object) to a Module
|
4
|
-
- Includes gen\_extend and gen\_include methods: generalizations
|
5
|
-
of Object#extend and Module#include that work with Objects and
|
6
|
-
Classes as well as Modules
|
7
|
-
|
8
|
-
How it works:
|
9
|
-
|
10
|
-
- First creates an IClass for the Class in question and sets the
|
11
|
-
T\_MODULE flag
|
12
|
-
- Recursively converts superclasses of the Class to IClasses
|
13
|
-
creating a modulified version of the Class's inheritance chain
|
14
|
-
- gen\_include/gen\_extend automatically call #to\_module on the
|
15
|
-
Class/Object before inclusion/extension.
|
16
|
-
|
17
|
-
|
18
|
-
|
data/Rakefile
DELETED
@@ -1,84 +0,0 @@
|
|
1
|
-
require 'rake/clean'
|
2
|
-
|
3
|
-
OBJECT2MODULE_VERSION = "0.1.0"
|
4
|
-
|
5
|
-
$dlext = Config::CONFIG['DLEXT']
|
6
|
-
|
7
|
-
CLEAN.include("ext/*.#{$dlext}", "ext/*.log", "ext/*.o", "ext/*~", "ext/*#*", "ext/*.obj", "ext/*.def", "ext/*.pdb")
|
8
|
-
CLOBBER.include("**/*.#{$dlext}", "**/*~", "**/*#*", "**/*.log", "**/*.o", "doc/**")
|
9
|
-
|
10
|
-
$make_program = if RUBY_PLATFORM =~ /win/
|
11
|
-
"nmake"
|
12
|
-
else
|
13
|
-
"make"
|
14
|
-
end
|
15
|
-
|
16
|
-
task :default => [:build]
|
17
|
-
|
18
|
-
desc "Build Object2module"
|
19
|
-
task :build => :clean do
|
20
|
-
chdir("./ext/") do
|
21
|
-
ruby "extconf.rb"
|
22
|
-
sh "#{$make_program}"
|
23
|
-
cp "cobject2module.#{$dlext}", "../lib" , :verbose => true
|
24
|
-
|
25
|
-
if RUBY_PLATFORM =~ /mswin/
|
26
|
-
if RUBY_VERSION =~ /1.9/
|
27
|
-
File.rename("../lib/cobject2module.#{$dlext}",
|
28
|
-
"../lib/cobject2module.19.#{$dlext}")
|
29
|
-
else
|
30
|
-
File.rename("../lib/cobject2module.#{$dlext}",
|
31
|
-
"../lib/cobject2module.18.#{$dlext}")
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
require 'rake/gempackagetask'
|
38
|
-
specification = Gem::Specification.new do |s|
|
39
|
-
s.name = "object2module"
|
40
|
-
s.summary = "object2module enables ruby classes and objects to be used as modules"
|
41
|
-
s.version = OBJECT2MODULE_VERSION
|
42
|
-
s.date = Time.now.strftime '%Y-%m-%d'
|
43
|
-
s.author = "John Mair (banisterfiend)"
|
44
|
-
s.email = 'jrmair@gmail.com'
|
45
|
-
s.description = s.summary
|
46
|
-
s.require_path = 'lib'
|
47
|
-
s.homepage = "http://banisterfiend.wordpress.com"
|
48
|
-
s.has_rdoc = true
|
49
|
-
s.extra_rdoc_files = ["README.rdoc", "ext/object2module.c"]
|
50
|
-
s.rdoc_options << '--main' << 'README.rdoc'
|
51
|
-
s.files = ["Rakefile", "lib/object2module.rb", "README.rdoc"] +
|
52
|
-
FileList["ext/*.c", "ext/*.h", "ext/*.rb", "test/*.rb"].to_a
|
53
|
-
|
54
|
-
if RUBY_PLATFORM =~ /mswin/
|
55
|
-
s.platform = Gem::Platform::CURRENT
|
56
|
-
s.files += ["lib/cobject2module.18.so", "lib/cobject2module.19.so"]
|
57
|
-
|
58
|
-
else
|
59
|
-
s.platform = Gem::Platform::RUBY
|
60
|
-
s.extensions = ["ext/extconf.rb"]
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
# gem, rdoc, and test tasks below
|
65
|
-
|
66
|
-
Rake::GemPackageTask.new(specification) do |package|
|
67
|
-
package.need_zip = false
|
68
|
-
package.need_tar = false
|
69
|
-
end
|
70
|
-
|
71
|
-
require 'rake/rdoctask'
|
72
|
-
Rake::RDocTask.new do |rd|
|
73
|
-
rd.main = "README.rdoc"
|
74
|
-
rd.rdoc_files.include("README.rdoc", "ext/*.c")
|
75
|
-
end
|
76
|
-
|
77
|
-
require 'rake/testtask'
|
78
|
-
Rake::TestTask.new do |t|
|
79
|
-
t.test_files = FileList['test/test*.rb']
|
80
|
-
t.verbose = true
|
81
|
-
end
|
82
|
-
|
83
|
-
|
84
|
-
|
data/ext/compat.h
DELETED
@@ -1,18 +0,0 @@
|
|
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
|
-
/* macros for backwards compatibility with 1.8 */
|
9
|
-
#ifndef RUBY_19
|
10
|
-
# define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
|
11
|
-
# define RCLASS_SUPER(c) (RCLASS(c)->super)
|
12
|
-
# define RCLASS_IV_TBL(c) (RCLASS(c)->iv_tbl)
|
13
|
-
#endif
|
14
|
-
|
15
|
-
/* a useful macro. cannot use ordinary CLASS_OF as it does not return an lvalue */
|
16
|
-
#define KLASS_OF(c) (RBASIC(c)->klass)
|
17
|
-
|
18
|
-
#endif
|
data/ext/extconf.rb
DELETED
data/ext/object2module.c
DELETED
@@ -1,215 +0,0 @@
|
|
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
|
-
#ifdef RUBY_19
|
37
|
-
VALUE klass = class_alloc(T_ICLASS, rb_cClass);
|
38
|
-
#else
|
39
|
-
NEWOBJ(klass, struct RClass);
|
40
|
-
OBJSETUP(klass, rb_cClass, T_ICLASS);
|
41
|
-
#endif
|
42
|
-
|
43
|
-
if (BUILTIN_TYPE(module) == T_ICLASS) {
|
44
|
-
module = KLASS_OF(module);
|
45
|
-
}
|
46
|
-
|
47
|
-
if (!RCLASS_IV_TBL(module)) {
|
48
|
-
|
49
|
-
RCLASS_IV_TBL(module) = (struct st_table *)st_init_numtable();
|
50
|
-
}
|
51
|
-
|
52
|
-
/* assign iv_tbl, m_tbl and super */
|
53
|
-
RCLASS_IV_TBL(klass) = RCLASS_IV_TBL(module);
|
54
|
-
RCLASS_SUPER(klass) = sup;
|
55
|
-
if(TYPE(module) != T_OBJECT) {
|
56
|
-
|
57
|
-
RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
|
58
|
-
}
|
59
|
-
else {
|
60
|
-
RCLASS_M_TBL(klass) = RCLASS_M_TBL(CLASS_OF(module));
|
61
|
-
}
|
62
|
-
|
63
|
-
/* */
|
64
|
-
|
65
|
-
if (TYPE(module) == T_ICLASS) {
|
66
|
-
KLASS_OF(klass) = KLASS_OF(module);
|
67
|
-
}
|
68
|
-
else {
|
69
|
-
KLASS_OF(klass) = module;
|
70
|
-
}
|
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
|
-
static VALUE
|
81
|
-
rb_to_module(VALUE self) {
|
82
|
-
VALUE rclass, chain_start, jcur, klass;
|
83
|
-
|
84
|
-
switch(BUILTIN_TYPE(self)) {
|
85
|
-
case T_MODULE:
|
86
|
-
return self;
|
87
|
-
case T_CLASS:
|
88
|
-
klass = self;
|
89
|
-
break;
|
90
|
-
case T_OBJECT:
|
91
|
-
default:
|
92
|
-
klass = rb_singleton_class(self);
|
93
|
-
}
|
94
|
-
|
95
|
-
chain_start = j_class_new(klass, rb_cObject);
|
96
|
-
|
97
|
-
KLASS_OF(chain_start) = rb_cModule;
|
98
|
-
RBASIC(chain_start)->flags = T_MODULE;
|
99
|
-
|
100
|
-
jcur = chain_start;
|
101
|
-
for(rclass = RCLASS_SUPER(klass); rclass != rb_cObject;
|
102
|
-
rclass = RCLASS_SUPER(rclass)) {
|
103
|
-
|
104
|
-
RCLASS_SUPER(jcur) = j_class_new(rclass, rb_cObject);
|
105
|
-
jcur = RCLASS_SUPER(jcur);
|
106
|
-
}
|
107
|
-
|
108
|
-
RCLASS_SUPER(jcur) = (VALUE)NULL;
|
109
|
-
|
110
|
-
return chain_start;
|
111
|
-
}
|
112
|
-
|
113
|
-
static VALUE
|
114
|
-
rb_reset_tbls(VALUE self) {
|
115
|
-
RCLASS_IV_TBL(self) = (struct st_table *) 0;
|
116
|
-
RCLASS_M_TBL(self) = (struct st_table *) st_init_numtable();
|
117
|
-
|
118
|
-
return Qnil;
|
119
|
-
}
|
120
|
-
|
121
|
-
/*
|
122
|
-
* call-seq:
|
123
|
-
* obj.gen_extend(other, ...) => obj
|
124
|
-
*
|
125
|
-
* Adds to _obj_ the instance methods from each object given as a
|
126
|
-
* parameter.
|
127
|
-
*
|
128
|
-
* class C
|
129
|
-
* def hello
|
130
|
-
* "Hello from C.\n"
|
131
|
-
* end
|
132
|
-
* end
|
133
|
-
*
|
134
|
-
* class Klass
|
135
|
-
* def hello
|
136
|
-
* "Hello from Klass.\n"
|
137
|
-
* end
|
138
|
-
* end
|
139
|
-
*
|
140
|
-
* k = Klass.new
|
141
|
-
* k.hello #=> "Hello from Klass.\n"
|
142
|
-
* k.gen_extend(C) #=> #<Klass:0x401b3bc8>
|
143
|
-
* k.hello #=> "Hello from C.\n"
|
144
|
-
*/
|
145
|
-
|
146
|
-
static VALUE
|
147
|
-
rb_gen_extend(int argc, VALUE * argv, VALUE self) {
|
148
|
-
int i;
|
149
|
-
|
150
|
-
if (argc == 0) rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
|
151
|
-
|
152
|
-
rb_singleton_class(self);
|
153
|
-
|
154
|
-
for(i = 0; i < argc; i++) {
|
155
|
-
VALUE mod = rb_to_module(argv[i]);
|
156
|
-
rb_funcall(mod, rb_intern("extend_object"), 1, self);
|
157
|
-
rb_funcall(mod, rb_intern("extended"), 1, self);
|
158
|
-
|
159
|
-
/* only redirect if argv[i] is not a module */
|
160
|
-
if(argv[i] != mod) rb_reset_tbls(mod);
|
161
|
-
}
|
162
|
-
|
163
|
-
return self;
|
164
|
-
}
|
165
|
-
|
166
|
-
/*
|
167
|
-
* call-seq:
|
168
|
-
* gen_include(other, ...) => self
|
169
|
-
*
|
170
|
-
* Adds to the implied receiver the instance methods from each object given as a
|
171
|
-
* parameter.
|
172
|
-
*
|
173
|
-
* class C
|
174
|
-
* def hello
|
175
|
-
* "Hello from C.\n"
|
176
|
-
* end
|
177
|
-
* end
|
178
|
-
*
|
179
|
-
* class Klass
|
180
|
-
* gen_include(C)
|
181
|
-
* end
|
182
|
-
*
|
183
|
-
* k = Klass.new
|
184
|
-
* k.hello #=> "Hello from C.\n"
|
185
|
-
*/
|
186
|
-
|
187
|
-
static VALUE
|
188
|
-
rb_gen_include(int argc, VALUE * argv, VALUE self) {
|
189
|
-
int i;
|
190
|
-
|
191
|
-
if (argc == 0) rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
|
192
|
-
|
193
|
-
for(i = 0; i < argc; i++) {
|
194
|
-
VALUE mod = rb_to_module(argv[i]);
|
195
|
-
rb_funcall(mod, rb_intern("append_features"), 1, self);
|
196
|
-
rb_funcall(mod, rb_intern("included"), 1, self);
|
197
|
-
|
198
|
-
if(argv[i] != mod) rb_reset_tbls(mod);
|
199
|
-
}
|
200
|
-
|
201
|
-
return self;
|
202
|
-
}
|
203
|
-
|
204
|
-
|
205
|
-
void Init_cobject2module() {
|
206
|
-
|
207
|
-
/* too dangerous as may result in double free. */
|
208
|
-
rb_define_method(rb_cObject, "to_module", rb_to_module , 0);
|
209
|
-
|
210
|
-
/* these methods are fine */
|
211
|
-
rb_define_method(rb_cObject, "gen_extend", rb_gen_extend, -1);
|
212
|
-
rb_define_method(rb_cModule, "gen_include", rb_gen_include, -1);
|
213
|
-
rb_define_method(rb_cModule, "reset_tbls", rb_reset_tbls, 0);
|
214
|
-
}
|
215
|
-
|
data/ext/object2module.h
DELETED
@@ -1,11 +0,0 @@
|
|
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
|