object2module 0.1.0 → 0.1.2
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.
- 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
|