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.
Files changed (80) hide show
  1. data/Rakefile +13 -13
  2. data/TODO +9 -41
  3. data/lib/rbplusplus/builders/allocation_strategy.rb +57 -0
  4. data/lib/rbplusplus/builders/base.rb +115 -212
  5. data/lib/rbplusplus/builders/class.rb +129 -115
  6. data/lib/rbplusplus/builders/const.rb +30 -0
  7. data/lib/rbplusplus/builders/const_converter.rb +52 -0
  8. data/lib/rbplusplus/builders/constructor.rb +19 -0
  9. data/lib/rbplusplus/builders/director.rb +149 -0
  10. data/lib/rbplusplus/builders/director_method.rb +20 -0
  11. data/lib/rbplusplus/builders/enumeration.rb +19 -26
  12. data/lib/rbplusplus/builders/extension.rb +42 -54
  13. data/lib/rbplusplus/builders/global_function.rb +18 -0
  14. data/lib/rbplusplus/builders/helpers/class.rb +74 -0
  15. data/lib/rbplusplus/builders/helpers/enumeration.rb +28 -0
  16. data/lib/rbplusplus/builders/helpers/module.rb +22 -0
  17. data/lib/rbplusplus/builders/include.rb +32 -0
  18. data/lib/rbplusplus/builders/instance_variable.rb +36 -0
  19. data/lib/rbplusplus/builders/method.rb +14 -0
  20. data/lib/rbplusplus/builders/method_base.rb +136 -0
  21. data/lib/rbplusplus/builders/module.rb +37 -51
  22. data/lib/rbplusplus/builders/module_function.rb +16 -0
  23. data/lib/rbplusplus/builders/static_method.rb +14 -0
  24. data/lib/rbplusplus/extension.rb +140 -28
  25. data/lib/rbplusplus/logger.rb +45 -0
  26. data/lib/rbplusplus/module.rb +55 -1
  27. data/lib/rbplusplus/transformers/class.rb +116 -35
  28. data/lib/rbplusplus/transformers/function.rb +14 -16
  29. data/lib/rbplusplus/transformers/method.rb +26 -1
  30. data/lib/rbplusplus/transformers/namespace.rb +12 -0
  31. data/lib/rbplusplus/transformers/node.rb +47 -54
  32. data/lib/rbplusplus/transformers/node_cache.rb +5 -9
  33. data/lib/rbplusplus/writers/multiple_files_writer.rb +290 -88
  34. data/lib/rbplusplus/writers/single_file_writer.rb +36 -14
  35. data/lib/rbplusplus.rb +44 -18
  36. data/test/allocation_strategies_test.rb +33 -0
  37. data/test/class_methods_encapsulate_test.rb +59 -0
  38. data/test/class_methods_test.rb +2 -35
  39. data/test/classes_test.rb +72 -2
  40. data/test/compiling_test.rb +13 -0
  41. data/test/constructors_test.rb +9 -18
  42. data/test/custom_code_test.rb +53 -0
  43. data/test/default_arguments_test.rb +69 -0
  44. data/test/director_test.rb +173 -0
  45. data/test/enumerations_test.rb +29 -0
  46. data/test/extension_test.rb +7 -2
  47. data/test/file_writers_test.rb +11 -4
  48. data/test/function_pointer_test.rb +56 -0
  49. data/test/function_pointers_classes_test.rb +27 -0
  50. data/test/generated/extconf.rb +2 -2
  51. data/test/headers/Adder.cpp +8 -0
  52. data/test/headers/Adder.h +31 -1
  53. data/test/headers/alloc_strats.h +26 -0
  54. data/test/headers/class_methods.h +30 -0
  55. data/test/headers/code/custom_to_from_ruby.cpp +11 -0
  56. data/test/headers/code/custom_to_from_ruby.hpp +13 -0
  57. data/test/headers/constructors.h +8 -20
  58. data/test/headers/default_arguments.h +49 -0
  59. data/test/headers/director.h +148 -0
  60. data/test/headers/enums.h +33 -0
  61. data/test/headers/function_pointers.h +32 -0
  62. data/test/headers/function_pointers_class.h +26 -0
  63. data/test/headers/needs_code.h +10 -0
  64. data/test/headers/overload.h +0 -3
  65. data/test/headers/subclass.h +10 -0
  66. data/test/headers/to_from_ruby.h +6 -4
  67. data/test/headers/ugly_interface.h +4 -7
  68. data/test/modules_test.rb +11 -6
  69. data/test/overloading_test.rb +6 -2
  70. data/test/subclass_test.rb +20 -10
  71. data/test/test_helper.rb +6 -1
  72. data/test/to_from_ruby_test.rb +0 -2
  73. data/test/wrap_as_test.rb +28 -37
  74. metadata +89 -57
  75. data/lib/rbplusplus/builders/types_manager.rb +0 -93
  76. data/lib/rbplusplus/transformers/constructor.rb +0 -4
  77. data/lib/rbplusplus/transformers/module.rb +0 -71
  78. data/lib/rbplusplus/transformers/node_reference.rb +0 -30
  79. data/test/headers/ugly_helper.h +0 -18
  80. data/test/object_persistence_test.rb +0 -44
@@ -1,73 +1,61 @@
1
1
  module RbPlusPlus
2
2
  module Builders
3
3
 
4
- # This class takes in all classes to be wrapped and builds
5
- # the top-level extension Init code
6
- class ExtensionBuilder < Base
7
-
8
- # Need to be given the list of modules as they are a special case
9
- attr_accessor :modules
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
- def build
12
- includes << "#include <rice/global_function.hpp>"
13
+ attr_reader :additional_includes
13
14
 
14
- add_additional_includes
15
+ def initialize(name, code, modules)
16
+ self.name = name
17
+ self.modules = modules
15
18
 
16
- body << "extern \"C\""
17
- body << "void Init_#{@name}() {"
19
+ @additional_includes = []
18
20
 
19
- # Explicitly ignore anything from the :: namespace
20
- if @node.name != "::"
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
- if func.return_type.const? || func.const?
42
- TypesManager.build_const_converter(func.return_type)
43
- end
24
+ def qualified_name
25
+ name
26
+ end
44
27
 
45
- ruby_name = "#{Inflector.underscore(func.name)}#{func_append}"
46
- body << "\tdefine_global_function(\"#{ruby_name}\", &#{wrapper_name});"
47
- end
48
- end
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
- build_modules
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
- def build_modules
58
- @modules.each do |mod|
59
- builder = ModuleBuilder.new(self, mod)
60
- builder.build
61
- builders << builder
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,14 @@
1
+ module RbPlusPlus
2
+ module Builders
3
+
4
+ # Wrap up an indivitual method
5
+ class MethodNode < MethodBase
6
+
7
+ def build
8
+ self.rice_method = "define_method"
9
+ end
10
+
11
+ end
12
+
13
+ end
14
+ 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
- # This class handles generating source for a requested Module
5
- class ModuleBuilder < Base
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
- # Initializer takes the parent object and the RbModule construction
8
- def initialize(parent, mod)
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
- def build
15
- # Using qualified name with underscores here to allow for nested modules
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
- includes << "#include <rice/Module.hpp>"
21
-
22
- add_additional_includes
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
- mod_defn = "\t#{rice_variable_type} #{rice_variable} = "
25
- if !parent.is_a?(ExtensionBuilder)
26
- mod_defn += "Rice::define_module_under(#{parent.rice_variable}, \"#{name}\");"
27
- else
28
- mod_defn += "Rice::define_module(\"#{name}\");"
29
- end
21
+ @name ||= code.name
22
+ @modules ||= code.modules
23
+ end
30
24
 
31
- body << mod_defn
25
+ def qualified_name
26
+ self.code.qualified_name
27
+ end
32
28
 
33
- # If a namespace has been given to this module, find and wrap the appropriate code
34
- if self.node
35
- build_enumerations
36
- end
29
+ def build
30
+ with_modules
37
31
 
38
- build_functions unless @module.functions.empty?
39
- build_classes(@module.classes) unless @module.classes.empty?
40
-
32
+ add_child IncludeNode.new(self, "rice/Module.hpp", :system)
41
33
 
42
- # Build each inner module
43
- @module.modules.each do |mod|
44
- builder = ModuleBuilder.new(self, mod)
45
- builder.build
46
- builders << builder
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
- # Process functions to be added to this module
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
- func_name = Inflector.underscore(func.name)
57
- wrapped_name = func.special_qualified_name || build_function_wrapper(func)
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
- # Special name handling. Qualified name is simply the name of this module
63
- def qualified_name
64
- if parent.is_a?(ModuleBuilder)
65
- "#{parent.qualified_name}::#{self.name}"
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
- self.name
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
@@ -0,0 +1,14 @@
1
+ module RbPlusPlus
2
+ module Builders
3
+
4
+ # Wrap up a static method on a class
5
+ class StaticMethodNode < MethodBase
6
+
7
+ def build
8
+ self.rice_method = "define_singleton_method"
9
+ end
10
+
11
+ end
12
+
13
+ end
14
+ end