rbplusplus 0.8 → 0.9
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/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
|