rbplusplus 0.8 → 0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +13 -13
- data/TODO +9 -41
- data/lib/rbplusplus/builders/allocation_strategy.rb +57 -0
- data/lib/rbplusplus/builders/base.rb +115 -212
- data/lib/rbplusplus/builders/class.rb +129 -115
- data/lib/rbplusplus/builders/const.rb +30 -0
- data/lib/rbplusplus/builders/const_converter.rb +52 -0
- data/lib/rbplusplus/builders/constructor.rb +19 -0
- data/lib/rbplusplus/builders/director.rb +149 -0
- data/lib/rbplusplus/builders/director_method.rb +20 -0
- data/lib/rbplusplus/builders/enumeration.rb +19 -26
- data/lib/rbplusplus/builders/extension.rb +42 -54
- data/lib/rbplusplus/builders/global_function.rb +18 -0
- data/lib/rbplusplus/builders/helpers/class.rb +74 -0
- data/lib/rbplusplus/builders/helpers/enumeration.rb +28 -0
- data/lib/rbplusplus/builders/helpers/module.rb +22 -0
- data/lib/rbplusplus/builders/include.rb +32 -0
- data/lib/rbplusplus/builders/instance_variable.rb +36 -0
- data/lib/rbplusplus/builders/method.rb +14 -0
- data/lib/rbplusplus/builders/method_base.rb +136 -0
- data/lib/rbplusplus/builders/module.rb +37 -51
- data/lib/rbplusplus/builders/module_function.rb +16 -0
- data/lib/rbplusplus/builders/static_method.rb +14 -0
- data/lib/rbplusplus/extension.rb +140 -28
- data/lib/rbplusplus/logger.rb +45 -0
- data/lib/rbplusplus/module.rb +55 -1
- data/lib/rbplusplus/transformers/class.rb +116 -35
- data/lib/rbplusplus/transformers/function.rb +14 -16
- data/lib/rbplusplus/transformers/method.rb +26 -1
- data/lib/rbplusplus/transformers/namespace.rb +12 -0
- data/lib/rbplusplus/transformers/node.rb +47 -54
- data/lib/rbplusplus/transformers/node_cache.rb +5 -9
- data/lib/rbplusplus/writers/multiple_files_writer.rb +290 -88
- data/lib/rbplusplus/writers/single_file_writer.rb +36 -14
- data/lib/rbplusplus.rb +44 -18
- data/test/allocation_strategies_test.rb +33 -0
- data/test/class_methods_encapsulate_test.rb +59 -0
- data/test/class_methods_test.rb +2 -35
- data/test/classes_test.rb +72 -2
- data/test/compiling_test.rb +13 -0
- data/test/constructors_test.rb +9 -18
- data/test/custom_code_test.rb +53 -0
- data/test/default_arguments_test.rb +69 -0
- data/test/director_test.rb +173 -0
- data/test/enumerations_test.rb +29 -0
- data/test/extension_test.rb +7 -2
- data/test/file_writers_test.rb +11 -4
- data/test/function_pointer_test.rb +56 -0
- data/test/function_pointers_classes_test.rb +27 -0
- data/test/generated/extconf.rb +2 -2
- data/test/headers/Adder.cpp +8 -0
- data/test/headers/Adder.h +31 -1
- data/test/headers/alloc_strats.h +26 -0
- data/test/headers/class_methods.h +30 -0
- data/test/headers/code/custom_to_from_ruby.cpp +11 -0
- data/test/headers/code/custom_to_from_ruby.hpp +13 -0
- data/test/headers/constructors.h +8 -20
- data/test/headers/default_arguments.h +49 -0
- data/test/headers/director.h +148 -0
- data/test/headers/enums.h +33 -0
- data/test/headers/function_pointers.h +32 -0
- data/test/headers/function_pointers_class.h +26 -0
- data/test/headers/needs_code.h +10 -0
- data/test/headers/overload.h +0 -3
- data/test/headers/subclass.h +10 -0
- data/test/headers/to_from_ruby.h +6 -4
- data/test/headers/ugly_interface.h +4 -7
- data/test/modules_test.rb +11 -6
- data/test/overloading_test.rb +6 -2
- data/test/subclass_test.rb +20 -10
- data/test/test_helper.rb +6 -1
- data/test/to_from_ruby_test.rb +0 -2
- data/test/wrap_as_test.rb +28 -37
- metadata +89 -57
- data/lib/rbplusplus/builders/types_manager.rb +0 -93
- data/lib/rbplusplus/transformers/constructor.rb +0 -4
- data/lib/rbplusplus/transformers/module.rb +0 -71
- data/lib/rbplusplus/transformers/node_reference.rb +0 -30
- data/test/headers/ugly_helper.h +0 -18
- data/test/object_persistence_test.rb +0 -44
@@ -1,73 +1,61 @@
|
|
1
1
|
module RbPlusPlus
|
2
2
|
module Builders
|
3
3
|
|
4
|
-
#
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
# Extension node.
|
5
|
+
# There is only ever one of these in a project as this is
|
6
|
+
# the top level node for building a Ruby extension.
|
7
|
+
#
|
8
|
+
# Extensions are effectively Modules with some slightly different
|
9
|
+
# symantics, in that they expose to Kernel and have slightly
|
10
|
+
# different function handling and code generation.
|
11
|
+
class ExtensionNode < ModuleNode
|
10
12
|
|
11
|
-
|
12
|
-
includes << "#include <rice/global_function.hpp>"
|
13
|
+
attr_reader :additional_includes
|
13
14
|
|
14
|
-
|
15
|
+
def initialize(name, code, modules)
|
16
|
+
self.name = name
|
17
|
+
self.modules = modules
|
15
18
|
|
16
|
-
|
17
|
-
body << "void Init_#{@name}() {"
|
19
|
+
@additional_includes = []
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
#Build a hash table to handle overloaded functions
|
23
|
-
func_hash = {}
|
24
|
-
@node.functions.each do |func|
|
25
|
-
next if func.ignored? || func.moved?
|
26
|
-
|
27
|
-
func_hash[func.name] ||= []
|
28
|
-
func_hash[func.name] << func
|
29
|
-
end
|
30
|
-
#Iterate through the hash table to handle overloaded functions
|
31
|
-
func_hash.each do |key, funcs|
|
32
|
-
funcs.each_with_index do |func, i|
|
33
|
-
add_includes_for func
|
34
|
-
|
35
|
-
#append _#{i} to overloaded methods
|
36
|
-
#this needs to be done in both the wrapper function and the ruby function
|
37
|
-
func_append = ""
|
38
|
-
func_append = "_#{i}" if funcs.size > 1
|
39
|
-
wrapper_name = func.special_qualified_name || build_function_wrapper(func, func_append)
|
21
|
+
super(code, nil)
|
22
|
+
end
|
40
23
|
|
41
|
-
|
42
|
-
|
43
|
-
|
24
|
+
def qualified_name
|
25
|
+
name
|
26
|
+
end
|
44
27
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
build_enumerations
|
51
|
-
build_classes
|
28
|
+
def add_includes(includes)
|
29
|
+
@additional_includes << includes
|
30
|
+
includes.each do |inc|
|
31
|
+
add_child IncludeNode.new(self, inc)
|
52
32
|
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def build
|
36
|
+
super
|
37
|
+
self.rice_variable = nil
|
38
|
+
self.rice_variable_type = nil
|
39
|
+
end
|
53
40
|
|
54
|
-
|
41
|
+
def write
|
42
|
+
# Let nodes build their code, splitting up code blocks into
|
43
|
+
# includes, declarations, and registrations,
|
44
|
+
# then wrap it up in our own template
|
45
|
+
registrations << "extern \"C\""
|
46
|
+
registrations << "void Init_#{@name}() {"
|
55
47
|
end
|
56
48
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
49
|
+
private
|
50
|
+
|
51
|
+
def with_module_functions
|
52
|
+
@code.functions.each do |func|
|
53
|
+
next if do_not_wrap?(func)
|
54
|
+
add_child GlobalFunctionNode.new(func, self)
|
62
55
|
end
|
63
56
|
end
|
64
57
|
|
65
|
-
# Finish up the required code before doing final output
|
66
|
-
def to_s
|
67
|
-
includes << "using namespace Rice;"
|
68
|
-
|
69
|
-
super + "\n}"
|
70
|
-
end
|
71
58
|
end
|
59
|
+
|
72
60
|
end
|
73
61
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
module Builders
|
3
|
+
|
4
|
+
# Expose a global function
|
5
|
+
class GlobalFunctionNode < MethodBase
|
6
|
+
|
7
|
+
def build
|
8
|
+
add_child IncludeNode.new(self, "rice/global_function.hpp", :system)
|
9
|
+
add_child IncludeNode.new(self, code.file)
|
10
|
+
|
11
|
+
self.prefix = "Rice::"
|
12
|
+
self.rice_method = "define_global_function"
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
module Builders
|
3
|
+
module ClassHelpers
|
4
|
+
|
5
|
+
# Build up any classes or structs under this module
|
6
|
+
def with_classes
|
7
|
+
[
|
8
|
+
self.code.classes,
|
9
|
+
self.code.structs
|
10
|
+
].flatten.each do |klass|
|
11
|
+
next if do_not_wrap?(klass)
|
12
|
+
add_child ClassNode.new(klass, self)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Wrap any constructors for this class
|
17
|
+
def with_constructors
|
18
|
+
# Ignore constructors on classes that have pure virtual methods,
|
19
|
+
# as they aren't constructable
|
20
|
+
return if !@director && self.code.pure_virtual?
|
21
|
+
|
22
|
+
to_use = self.code._get_constructor
|
23
|
+
|
24
|
+
real_constructors = [self.code.constructors].flatten.select {|c| !c.attributes[:artificial]}
|
25
|
+
|
26
|
+
if real_constructors.empty?
|
27
|
+
real_constructors = self.code.constructors
|
28
|
+
else
|
29
|
+
ignore_artificial = true
|
30
|
+
end
|
31
|
+
|
32
|
+
if to_use.nil? && real_constructors.length > 1
|
33
|
+
Logger.warn :multiple_constructors, "#{self.code.qualified_name} has multiple constructors. " +
|
34
|
+
"While the extension will probably compile, Rice only supports one constructor, " +
|
35
|
+
"please use #use_contructor to select which one to use."
|
36
|
+
end
|
37
|
+
|
38
|
+
# First, lets see if we have any non-generated constructors
|
39
|
+
|
40
|
+
[to_use || real_constructors].flatten.each do |constructor|
|
41
|
+
next if do_not_wrap?(constructor)
|
42
|
+
|
43
|
+
if constructor.attributes[:artificial]
|
44
|
+
next if ignore_artificial || constructor.arguments.length == 1
|
45
|
+
end
|
46
|
+
|
47
|
+
if @director
|
48
|
+
@director.wrap_constructor constructor
|
49
|
+
else
|
50
|
+
add_child ConstructorNode.new(constructor, self)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Wrap up any class constants
|
56
|
+
def with_constants
|
57
|
+
[self.code.constants].flatten.each do |const|
|
58
|
+
next if do_not_wrap?(const)
|
59
|
+
add_child ConstNode.new(const, self)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Expose the public variables for this class
|
64
|
+
def with_variables
|
65
|
+
[self.code.variables].flatten.each do |var|
|
66
|
+
next if do_not_wrap?(var)
|
67
|
+
|
68
|
+
add_child InstanceVariableNode.new(var, self)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
module Builders
|
3
|
+
module EnumerationHelpers
|
4
|
+
|
5
|
+
# Wrap up enumerations for this node.
|
6
|
+
# Anonymous enumerations are a special case. C++ doesn't
|
7
|
+
# see them as a seperate type and instead are just "scoped" constants,
|
8
|
+
# so we have to wrap them as such, constants.
|
9
|
+
def with_enumerations
|
10
|
+
[self.code.enumerations].flatten.each do |enum|
|
11
|
+
next if do_not_wrap?(enum)
|
12
|
+
|
13
|
+
if enum.anonymous?
|
14
|
+
# So for each value of this enumeration,
|
15
|
+
# expose it as a constant
|
16
|
+
enum.values.each do |value|
|
17
|
+
add_child ConstNode.new(value, self)
|
18
|
+
end
|
19
|
+
else
|
20
|
+
add_child EnumerationNode.new(enum, self)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
module Builders
|
3
|
+
module ModuleHelpers
|
4
|
+
|
5
|
+
# Build up any user-defined modules for this node
|
6
|
+
def with_modules
|
7
|
+
self.modules.each do |mod|
|
8
|
+
add_child ModuleNode.new(mod, self)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# Expose a function in this module
|
13
|
+
def with_module_functions
|
14
|
+
[self.code.functions].flatten.each do |func|
|
15
|
+
next if do_not_wrap?(func)
|
16
|
+
add_child ModuleFunctionNode.new(func, self)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
module Builders
|
3
|
+
|
4
|
+
# Node for an #include line.
|
5
|
+
# Can be a :local (default) or :system
|
6
|
+
# include declaration.
|
7
|
+
#
|
8
|
+
# Includes have no children
|
9
|
+
class IncludeNode < Base
|
10
|
+
|
11
|
+
def initialize(parent, path, type = :local)
|
12
|
+
super(nil, parent)
|
13
|
+
|
14
|
+
@path = path
|
15
|
+
@type = type
|
16
|
+
end
|
17
|
+
|
18
|
+
def build
|
19
|
+
#nop
|
20
|
+
end
|
21
|
+
|
22
|
+
def write
|
23
|
+
if @path
|
24
|
+
includes << (@type == :local ? "#include \"#{@path}\"" : "#include <#{@path}>")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
module Builders
|
3
|
+
|
4
|
+
# Wrap up a class instance variable
|
5
|
+
class InstanceVariableNode < Base
|
6
|
+
|
7
|
+
def build
|
8
|
+
end
|
9
|
+
|
10
|
+
def write
|
11
|
+
ruby_name = Inflector.underscore(code.name)
|
12
|
+
parent_name = parent.code.qualified_name.as_variable
|
13
|
+
|
14
|
+
# Setter, only if it isn't const
|
15
|
+
if !code.cpp_type.const?
|
16
|
+
method_name = "wrap_#{parent_name}_#{code.name}_set"
|
17
|
+
declarations << "void #{method_name}(#{parent.code.qualified_name}* self, #{code.cpp_type.base_type.qualified_name} val) {"
|
18
|
+
declarations << "self->#{code.name} = val;"
|
19
|
+
declarations << "}"
|
20
|
+
|
21
|
+
registrations << "#{parent.rice_variable}.define_method(\"#{ruby_name}=\", &#{method_name});"
|
22
|
+
end
|
23
|
+
|
24
|
+
# Getter
|
25
|
+
method_name = "wrap_#{parent_name}_#{code.name}_get"
|
26
|
+
declarations << "#{code.cpp_type.base_type.qualified_name} #{method_name}(#{parent.code.qualified_name}* self) {"
|
27
|
+
declarations << "return self->#{code.name};"
|
28
|
+
declarations << "}"
|
29
|
+
|
30
|
+
registrations << "#{parent.rice_variable}.define_method(\"#{ruby_name}\", &#{method_name});"
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
module Builders
|
3
|
+
|
4
|
+
# Base class for any type of method or function handling
|
5
|
+
class MethodBase < Base
|
6
|
+
|
7
|
+
attr_accessor :prefix, :rice_method, :suffix
|
8
|
+
|
9
|
+
def initialize(code, parent = nil)
|
10
|
+
super
|
11
|
+
|
12
|
+
# Overload checks:
|
13
|
+
# - If we're the only one, no overload required
|
14
|
+
# - If we're one of many w/ the same name:
|
15
|
+
# - Find out which in the list we are
|
16
|
+
# - Add the number to ruby_name, unless user has renamed
|
17
|
+
# - Build typedef of the method and use it in the exposure
|
18
|
+
found = [code.parent.methods(code.name)].flatten
|
19
|
+
if found.length > 1 && !code.renamed?
|
20
|
+
num = found.index(code)
|
21
|
+
self.suffix = "_#{num}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Wrap up this method making sure that overloads
|
26
|
+
# are properly typedef'd to keep from compiler error from unresolvable types
|
27
|
+
#
|
28
|
+
# Thanks to Py++ for the appropriate C++ syntax for this.
|
29
|
+
def write
|
30
|
+
@ruby_name = Inflector.underscore(code.name)
|
31
|
+
|
32
|
+
self.prefix ||= "#{self.parent.rice_variable}."
|
33
|
+
self.suffix ||= ""
|
34
|
+
|
35
|
+
if self.code.arguments.size == 1 && (fp = self.code.arguments[0].cpp_type.base_type).is_a?(RbGCCXML::FunctionType)
|
36
|
+
wrap_with_function_pointer(fp)
|
37
|
+
else
|
38
|
+
wrap_normal_method
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# This method should return the full C++ path to the method you're exposing
|
43
|
+
def code_path
|
44
|
+
self.code.qualified_name
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
# Handling methods that take function pointers takes a lot of extra custom code.
|
50
|
+
# - Need a method that acts as the proxy between C and the Ruby proc
|
51
|
+
# - Need a method that gets wrapped into Ruby to handle type conversions
|
52
|
+
#
|
53
|
+
def wrap_with_function_pointer(func_pointer)
|
54
|
+
Logger.info "Building callback wrapper for #{self.code.qualified_name}"
|
55
|
+
|
56
|
+
base_name = self.code.qualified_name.as_variable
|
57
|
+
return_type = func_pointer.return_type.to_cpp
|
58
|
+
proxy_method_name = "do_yield_on_#{base_name}"
|
59
|
+
|
60
|
+
callback_arguments = []
|
61
|
+
callback_values = [func_pointer.arguments.length]
|
62
|
+
|
63
|
+
func_pointer.arguments.each_with_index do |arg, i|
|
64
|
+
callback_arguments << "#{arg.to_cpp} arg#{i}"
|
65
|
+
callback_values << "to_ruby(arg#{i}).value()"
|
66
|
+
end
|
67
|
+
|
68
|
+
# Build the method that acts as the Proc -> C func pointer proxy (the callback)
|
69
|
+
block_var_name = "_block_for_#{base_name}"
|
70
|
+
declarations << "VALUE #{block_var_name};"
|
71
|
+
declarations << "#{return_type} #{proxy_method_name}(#{callback_arguments.join(", ")}) {"
|
72
|
+
|
73
|
+
funcall = "rb_funcall(#{block_var_name}, rb_intern(\"call\"), #{callback_values.join(", ")})"
|
74
|
+
if return_type == "void"
|
75
|
+
declarations << "#{funcall};"
|
76
|
+
else
|
77
|
+
declarations << "return from_ruby<#{return_type} >(#{funcall});"
|
78
|
+
end
|
79
|
+
|
80
|
+
declarations << "}"
|
81
|
+
|
82
|
+
if self.parent.is_a?(ClassNode)
|
83
|
+
arg = "#{self.parent.qualified_name} *self"
|
84
|
+
callee = "self->#{self.code.qualified_name}"
|
85
|
+
else
|
86
|
+
arg = ""
|
87
|
+
callee = "#{self.code.qualified_name}"
|
88
|
+
end
|
89
|
+
|
90
|
+
wrapper_func = "wrap_for_callback_#{base_name}"
|
91
|
+
|
92
|
+
# Build the wrapper method that gets exposed to Ruby
|
93
|
+
declarations << "VALUE #{wrapper_func}(#{arg}) {"
|
94
|
+
declarations << "\t#{block_var_name} = rb_block_proc();"
|
95
|
+
declarations << "\t#{callee}(&#{proxy_method_name});"
|
96
|
+
declarations << "\treturn Qnil;"
|
97
|
+
declarations << "}"
|
98
|
+
|
99
|
+
registrations << "#{self.prefix}#{self.rice_method}(\"#{@ruby_name + self.suffix}\", &#{wrapper_func});"
|
100
|
+
end
|
101
|
+
|
102
|
+
def wrap_normal_method
|
103
|
+
parts = "#{self.qualified_name}".split("::")
|
104
|
+
usage_ref = "#{parts[-1]}_func_type"
|
105
|
+
|
106
|
+
if self.code.static? || self.code.as_instance_method?
|
107
|
+
method_ref = "*#{usage_ref}"
|
108
|
+
else
|
109
|
+
method_ref = [parts[0..-2], "*#{usage_ref}"].flatten.join("::")
|
110
|
+
end
|
111
|
+
|
112
|
+
default_arguments = []
|
113
|
+
arguments = []
|
114
|
+
|
115
|
+
self.code.arguments.each do |arg|
|
116
|
+
arguments << arg.to_cpp
|
117
|
+
default_arguments << "Rice::Arg(\"#{arg.name}\")#{arg.value ? " = (#{arg.cpp_type.to_cpp})#{arg.value}" : "" }"
|
118
|
+
end
|
119
|
+
|
120
|
+
return_type = find_typedef_for(self.code.return_type).to_cpp
|
121
|
+
|
122
|
+
def_args = default_arguments.any? ? ", (#{default_arguments.join(", ")})" : ""
|
123
|
+
|
124
|
+
registrations << "{"
|
125
|
+
|
126
|
+
registrations << "typedef #{return_type} ( #{method_ref} )( #{arguments.join(", ")} );"
|
127
|
+
registrations << "#{self.prefix}#{self.rice_method}(\"#{@ruby_name + self.suffix}\", " +
|
128
|
+
"#{usage_ref}( &#{code_path} )#{def_args});"
|
129
|
+
|
130
|
+
registrations << "}"
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
@@ -1,73 +1,59 @@
|
|
1
1
|
module RbPlusPlus
|
2
2
|
module Builders
|
3
3
|
|
4
|
-
#
|
5
|
-
class
|
4
|
+
# Handles code generation dealing with user-defined modules.
|
5
|
+
class ModuleNode < Base
|
6
|
+
include ModuleHelpers
|
7
|
+
include EnumerationHelpers
|
8
|
+
include ClassHelpers
|
6
9
|
|
7
|
-
#
|
8
|
-
|
9
|
-
super(mod.name, mod.node)
|
10
|
-
@module = mod
|
11
|
-
self.parent = parent
|
12
|
-
end
|
10
|
+
# Has a name
|
11
|
+
attr_accessor :name
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
# of the same name
|
17
|
-
self.rice_variable = "rb_m#{self.qualified_name.gsub(/::/, "_")}"
|
18
|
-
self.rice_variable_type = "Rice::Module"
|
13
|
+
# And needs to specially handle any other nexted modules
|
14
|
+
attr_accessor :modules
|
19
15
|
|
20
|
-
|
21
|
-
|
22
|
-
|
16
|
+
# Node is the RbModule object, it proxies any unknown calls
|
17
|
+
# off to it's internal Node object
|
18
|
+
def initialize(code, parent = nil)
|
19
|
+
super
|
23
20
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
else
|
28
|
-
mod_defn += "Rice::define_module(\"#{name}\");"
|
29
|
-
end
|
21
|
+
@name ||= code.name
|
22
|
+
@modules ||= code.modules
|
23
|
+
end
|
30
24
|
|
31
|
-
|
25
|
+
def qualified_name
|
26
|
+
self.code.qualified_name
|
27
|
+
end
|
32
28
|
|
33
|
-
|
34
|
-
|
35
|
-
build_enumerations
|
36
|
-
end
|
29
|
+
def build
|
30
|
+
with_modules
|
37
31
|
|
38
|
-
|
39
|
-
build_classes(@module.classes) unless @module.classes.empty?
|
40
|
-
|
32
|
+
add_child IncludeNode.new(self, "rice/Module.hpp", :system)
|
41
33
|
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
34
|
+
# Make sure we ignore anything from the :: namespace
|
35
|
+
if self.code && self.code.name != "::"
|
36
|
+
with_module_functions
|
37
|
+
with_enumerations
|
38
|
+
with_classes
|
47
39
|
end
|
48
|
-
end
|
49
40
|
|
50
|
-
|
51
|
-
def build_functions
|
52
|
-
@module.functions.each do |func|
|
53
|
-
next if func.ignored? || func.moved? # fine grained function filtering
|
54
|
-
add_includes_for func
|
41
|
+
nodes.flatten!
|
55
42
|
|
56
|
-
|
57
|
-
|
58
|
-
body << "\t#{self.rice_variable}.define_module_function(\"#{func_name}\", &#{wrapped_name});"
|
59
|
-
end
|
43
|
+
self.rice_variable_type = "Rice::Module"
|
44
|
+
self.rice_variable = "rb_m#{self.qualified_name.as_variable}"
|
60
45
|
end
|
61
46
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
47
|
+
def write
|
48
|
+
prefix = "#{rice_variable_type} #{rice_variable} = "
|
49
|
+
|
50
|
+
if parent.rice_variable
|
51
|
+
registrations << "#{prefix} Rice::define_module_under(#{parent.rice_variable}, \"#{@name}\");"
|
66
52
|
else
|
67
|
-
|
53
|
+
registrations << "#{prefix} Rice::define_module(\"#{@name}\");"
|
68
54
|
end
|
69
55
|
end
|
70
|
-
|
71
56
|
end
|
57
|
+
|
72
58
|
end
|
73
59
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
module Builders
|
3
|
+
|
4
|
+
# Wrap up a method on a Module as a module_function
|
5
|
+
class ModuleFunctionNode < MethodBase
|
6
|
+
|
7
|
+
def build
|
8
|
+
add_child IncludeNode.new(self, code.file)
|
9
|
+
|
10
|
+
self.rice_method = "define_module_function"
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|