rbplusplus 0.8 → 0.9

Sign up to get free protection for your applications and to get access to all the features.
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,77 +1,70 @@
1
1
  module RbGCCXML
2
- class Node
3
- # Specifies to not export this node
2
+ class Node
3
+
4
+ # Specify to Rb++ that this node is not to be wrapped
4
5
  def ignore
5
- @ignored = true
6
+ cache[:ignored] = true
7
+ end
8
+
9
+ # Un-ignore this node, useful if there's a glob ignore and the wrapper
10
+ # just wants a few of the classes
11
+ def unignore
12
+ cache[:ignored] = false
6
13
  end
7
-
8
- # Returns true if this node is ignored in exporting
14
+
15
+ # Has this node been previously declared to not be wrapped?
9
16
  def ignored?
10
- @ignored || false
17
+ !!cache[:ignored]
11
18
  end
12
19
 
13
20
  # Specifies that this node has been included somewhere else
14
- def moved=(val)
15
- @moved = val
21
+ def moved_to=(val)
22
+ cache[:moved_to] = val
16
23
  end
17
-
24
+
18
25
  # Change what the name of this node will be when wrapped into Ruby
19
26
  def wrap_as(name)
20
- @renamed = name
27
+ cache[:wrap_as] = name
21
28
  self
22
29
  end
23
-
24
- # Returns true if the node has been moved
25
- def moved?
26
- @moved || false
30
+
31
+ # Where has this node moved to?
32
+ def moved_to
33
+ cache[:moved_to]
27
34
  end
28
-
35
+
29
36
  # Has this node been renamed
30
37
  def renamed?
31
- (@renamed.nil? ? false : true)
38
+ !!cache[:wrap_as]
32
39
  end
33
40
 
34
- alias_method :rbgccxml_namespaces, :namespaces
35
- def namespaces(*args) #:nodoc:
36
- nodes = rbgccxml_namespaces(*args)
37
- return cache(nodes)
41
+ alias_method :rbgccxml_name, :name
42
+ def name #:nodoc:
43
+ cache[:wrap_as] || rbgccxml_name
38
44
  end
39
-
40
- alias_method :rbgccxml_classes, :classes
41
- def classes(*args) #:nodoc:
42
- nodes = rbgccxml_classes(*args)
43
- return cache(nodes)
45
+
46
+ def cpp_name
47
+ rbgccxml_name
44
48
  end
45
-
46
- alias_method :rbgccxml_functions, :functions
47
- def functions(*args) #:nodoc:
48
- nodes = rbgccxml_functions(*args)
49
- return cache(nodes)
49
+
50
+ # In some cases, the automatic typedef lookup of rb++ can end up
51
+ # doing the wrong thing (for example, it can take a normal class
52
+ # and end up using the typedef for stl::container<>::value_type).
53
+ # Flag a given class as ignoring this typedef lookup if this
54
+ # situation happens.
55
+ def disable_typedef_lookup
56
+ cache[:disable_typedef_lookup] = true
50
57
  end
51
-
52
- alias_method :rbgccxml_methods, :functions
53
- def methods(*args) #:nodoc:
54
- nodes = rbgccxml_methods(*args)
55
- return cache(nodes)
56
- end
57
-
58
- alias_method :rbgccxml_name, :name
59
- def name #:nodoc:
60
- @renamed || rbgccxml_name
58
+
59
+ def _disable_typedef_lookup? #:nodoc:
60
+ !!cache[:disable_typedef_lookup]
61
61
  end
62
-
63
- private
64
- # Looks up the objects in the node cache.
65
- def cache(nodes)
66
- if nodes.is_a?(QueryResult)
67
- retv = QueryResult.new
68
- nodes.each do |node|
69
- retv << RbPlusPlus::NodeCache.instance.get(node)
70
- end
71
- return retv
72
- else
73
- return RbPlusPlus::NodeCache.instance.get(nodes)
74
- end
62
+
63
+ protected
64
+
65
+ # Get this node's settings cache
66
+ def cache
67
+ NodeCache.get(self)
75
68
  end
76
- end
69
+ end
77
70
  end
@@ -1,18 +1,14 @@
1
1
  module RbPlusPlus
2
2
  class NodeCache #:nodoc:
3
- include Singleton
4
- # Retrieves a node from the cache based on the node's qualified name
5
- def get(node)
6
- demangled = node.attributes['demangled']
3
+ # Retrieves or initializes a node's information cache
4
+ def self.get(node)
5
+ demangled = node.attributes['id']
7
6
  @@nodes ||= {}
8
- if @@nodes[demangled].nil?
9
- @@nodes[demangled] = node
10
- end
11
- return @@nodes[demangled]
7
+ @@nodes[demangled] ||= {}
12
8
  end
13
9
 
14
10
  # Clears out the cache
15
- def clear
11
+ def self.clear
16
12
  @@nodes = {}
17
13
  end
18
14
  end
@@ -4,120 +4,322 @@ module RbPlusPlus
4
4
  # multiple files.
5
5
  class MultipleFilesWriter < Base
6
6
 
7
+ # Writing out a multiple-file built is a multi-stage process. This writer
8
+ # first builds a [working_dir]/.build directory, where new code initially goes.
9
+ # Once the writing is complete, each file in .build/ is diff-checked by the files
10
+ # in [working_dir]. If the files are different, the new file is copied into place.
11
+ # Then, the .build dir is removed.
12
+ #
13
+ # We do this to allow for easy and quick-ish work on large wrapping projects. Because
14
+ # Rice code takes so long to compile, the fewer files one has to compile per change
15
+ # the better.
7
16
  def write
8
- @to_from_include = ""
9
- write_to_from_ruby
10
- _write_node(builder)
17
+ build_working_dir
18
+ write_files
19
+ process_diffs
20
+ cleanup
21
+ end
22
+
23
+ private
24
+
25
+ def build_working_dir
26
+ @build_dir = File.join(working_dir, ".build")
27
+
28
+ # Build our temp dir
29
+ FileUtils.mkdir_p @build_dir
30
+ end
31
+
32
+ # Go through each file in @build_dir and check them against
33
+ # the files in @working_dir, copying over only the ones
34
+ # that differ
35
+ def process_diffs
36
+ Dir["#{@build_dir}/*.{cpp,hpp}"].each do |file|
37
+ FileUtils.cp file, working_dir if files_differ(file)
38
+ end
39
+ end
40
+
41
+ def files_differ(file)
42
+ filename = File.basename(file)
43
+ existing = File.expand_path(File.join(working_dir, filename))
44
+ new = File.expand_path(File.join(@build_dir, filename))
45
+ return true if !File.exists?(existing)
46
+
47
+ !system("diff #{existing} #{new} > #{@build_dir}/diff_info 2>&1")
11
48
  end
12
49
 
13
- # Write out files that include the auto-generated to_/from_ruby constructs.
14
- def write_to_from_ruby
15
- # Ignore this if there's nothing to write out
16
- return if Builders::TypesManager.body.length == 0
50
+ def cleanup
51
+ FileUtils.rm_rf @build_dir
52
+ end
53
+
54
+ # Given our builder, go through nodes and write out files
55
+ def write_files
56
+ # Couple of steps here:
57
+ # - Split up the code into files according to Modules and Classes
58
+ # - Header files need a register_#{name} prototype, source needs
59
+ # register_#{name}(#{parent}) method definition
60
+ # - All includes for this node go in the header.
61
+ # - Source gets an include for the related header
62
+ # - Save up all data from global_children and at the end write out
63
+ # our rbpp_custom files, making sure all header files include
64
+ # rbpp_custom.hpp
65
+
66
+ @file_writers = []
67
+ @global_writer = RbppCustomFileWriter.new
68
+ @globals_handled = []
17
69
 
18
- hpp_file = File.join(working_dir, "_to_from_ruby.rb.hpp")
19
- cpp_file = File.join(working_dir, "_to_from_ruby.rb.cpp")
70
+ new_file_for(self.builder)
71
+ process_globals(self.builder)
20
72
 
21
- @to_from_include = "#include \"#{hpp_file}\""
73
+ @global_writer.with_includes(self.builder.additional_includes)
74
+ @global_writer.write(@build_dir)
22
75
 
23
- include_guard = "__RICE_GENERATED_TO_FROM_RUBY_HPP__"
76
+ # Write out from the bottom up, makes sure that children file writers
77
+ # update their parents as needed
78
+ @file_writers.each do |fw|
79
+ fw.write(@build_dir)
80
+ end
81
+ end
24
82
 
25
- File.open(hpp_file, "w+") do |f|
26
- f.puts "#ifndef #{include_guard}"
27
- f.puts "#define #{include_guard}"
28
- f.puts ""
29
- f.puts Builders::TypesManager.includes.uniq.join("\n")
30
- f.puts ""
31
- f.puts Builders::TypesManager.prototypes.join("\n")
32
- f.puts ""
33
- f.puts "#endif // #{include_guard}"
83
+ def process_globals(node)
84
+ # Process the globals
85
+ node.global_nodes.each do |g|
86
+ next if @globals_handled.include?(g.qualified_name)
87
+ @globals_handled << g.qualified_name
88
+ @global_writer << g
34
89
  end
35
90
 
36
- File.open(cpp_file, "w+") do |f|
37
- f.puts @to_from_include
38
- f.puts ""
39
- f.puts Builders::TypesManager.body.join("\n");
91
+ node.nodes.each do |b|
92
+ process_globals(b)
40
93
  end
41
94
  end
42
95
 
43
- # How this works:
44
- #
45
- # We'll recurse through the builder heirarchy, starting at the bottom.
46
- # This lets us to properly link up each file so that all classes / modules /
47
- # functions get properly exposed.
48
- def _write_node(node)
49
- node.builders.each do |b|
50
- _write_node(b)
51
- end
52
-
53
- filename = if node.parent
54
- "_"+node.qualified_name.gsub(/::/, "_")
55
- else
56
- node.name
57
- end
58
-
59
- #templated classes
60
- filename.gsub!(/[ ,<>]/,"_")
61
- #templates to pointers
62
- filename.gsub!("*","Ptr")
63
-
64
- cpp_file = File.join(working_dir, "#{filename}.rb.cpp")
65
-
66
- if node.parent
67
- hpp_file = File.join(working_dir, "#{filename}.rb.hpp")
68
- hpp_include = "#include \"#{hpp_file}\""
69
- register_func = "register_#{filename}"
70
-
71
- include_guard = "__RICE_GENERATED_#{filename}_HPP__"
72
-
73
- register_func_arg = ""
74
- register_func_prototype = ""
75
-
76
- if !node.parent.is_a?(Builders::ExtensionBuilder)
77
- register_func_arg = node.parent.rice_variable
78
- register_func_prototype = "#{node.parent.rice_variable_type} #{register_func_arg}"
96
+ def new_file_for(node, parent = nil)
97
+ file_writer = FileWriter.new(node, parent)
98
+ @file_writers << file_writer
99
+
100
+ process_file(file_writer, node)
101
+ end
102
+
103
+ # Recursively run through this node's children
104
+ # adding them to the given file_writer or spawning
105
+ # off another file writer depending on the type
106
+ # of node we hit
107
+ def process_file(file_writer, node)
108
+ node.nodes.each do |child|
109
+ if child.is_a?(Builders::ModuleNode) || child.is_a?(Builders::ClassNode)
110
+ new_file_for(child, file_writer)
111
+ else
112
+ file_writer << child
113
+ process_file(file_writer, child) if child.has_children?
79
114
  end
115
+ end
116
+ end
117
+
118
+ # For every file to write out, we build an instance of a FileWriter here.
119
+ # This class needs to be given all the nodes it will be writing out to a file
120
+ #
121
+ # To handle parents calling register_#{name}() on their children, it's up to the
122
+ # children writers to inform the parents of their existence
123
+ class FileWriter
124
+
125
+ attr_reader :base_name, :node
126
+
127
+ def initialize(node, parent)
128
+ @node = node
129
+ @base_name = node.qualified_name.as_variable
130
+
131
+ @header = parent ? "_#{@base_name}.rb.hpp" : nil
132
+ @source = parent ? "_#{@base_name}.rb.cpp" : "#{@base_name}.rb.cpp"
133
+ @parent = parent
134
+
135
+ @require_custom = false
136
+
137
+ @needs_closing = true
138
+
139
+ register_with_parent if @parent
140
+
141
+ @nodes = [@node]
142
+ end
143
+
144
+ # Add a node to this file writer
145
+ def <<(node)
146
+ @nodes << node
147
+ end
148
+
149
+ def write(build_dir)
150
+ @build_dir = build_dir
151
+
152
+ build_source
153
+ write_header if @header
154
+ write_source
155
+ end
156
+
157
+ def rice_type
158
+ @node.rice_variable_type
159
+ end
160
+
161
+ def rice_variable
162
+ @node.rice_variable
163
+ end
164
+
165
+ def has_rice_variable?
166
+ !@node.rice_variable.nil?
167
+ end
80
168
 
81
- # Changes we need to make to the parent for everything to work across multiple
82
- # files
83
- #
84
- # * Add an include to the hpp file
85
- # * Add a call to the register method
86
- node.parent.includes << hpp_include
169
+ def add_register_method(node_name, header)
170
+ @register_methods ||= []
171
+ @register_includes ||= []
87
172
 
88
- # Register for proper flattening of the inheritance tree
89
- node.parent.register_node(node, "#{register_func}(#{register_func_arg});")
173
+ @register_includes << "#include \"#{header}\""
174
+ @register_methods << "register_#{node_name}(#{has_rice_variable? ? self.rice_variable : ""});"
175
+ end
176
+
177
+ protected
178
+
179
+ def register_with_parent
180
+ @register_method = "void register_#{@base_name}"
181
+ @parent.add_register_method @base_name, @header
182
+ end
183
+
184
+ def build_source
185
+ @includes = []
186
+ @declarations = []
187
+ @registrations = []
188
+
189
+ @nodes.each do |node|
190
+ node.write
191
+ @includes << node.includes
192
+ @declarations << node.declarations
193
+ @registrations << node.registrations
194
+ end
195
+ end
196
+
197
+ def parent_signature
198
+ if @parent && @parent.has_rice_variable?
199
+ "#{@parent.rice_type} #{@parent.rice_variable}"
200
+ else
201
+ ""
202
+ end
203
+ end
90
204
 
91
- # Modifications to this current node's code:
92
- #
93
- # * Add a register prototype to the header file
94
- # * Set include in node to the header file
95
- # * Wrap the body in a register method
205
+ def write_header
206
+ include_guard = "__RICE_GENERATED_#{@base_name}_HPP__"
96
207
 
97
- File.open(hpp_file, "w+") do |hpp|
208
+ File.open(File.join(@build_dir, @header), "w+") do |hpp|
98
209
  hpp.puts "#ifndef #{include_guard}"
99
210
  hpp.puts "#define #{include_guard}"
100
- hpp.puts ""
101
- hpp.puts @to_from_include
102
- hpp.puts ""
103
- hpp.puts "void #{register_func}(#{register_func_prototype});"
104
- hpp.puts "#endif"
105
- end
211
+ hpp.puts
212
+
213
+ custom_name = "_rbpp_custom.rb.hpp"
214
+ hpp.puts "#include \"#{custom_name}\"" if File.exists?(File.join(@build_dir, custom_name))
106
215
 
107
- node.includes << hpp_include
216
+ if @register_method
217
+ hpp.puts "#{@register_method}(#{parent_signature});"
218
+ end
108
219
 
109
- node.body = [
110
- "void #{register_func}(#{register_func_prototype}) {",
111
- node.body,
112
- "}"
113
- ]
220
+ hpp.puts
221
+ hpp.puts "#endif // #{include_guard}"
222
+ end
114
223
  end
115
224
 
116
- File.open(cpp_file, "w+") do |cpp|
117
- cpp.puts node.to_s
225
+ def write_source
226
+ File.open(File.join(@build_dir, @source), "w+") do |cpp|
227
+ if (incls = @includes.flatten.compact).any?
228
+ cpp.puts "", incls.uniq.sort.reverse.join("\n"), ""
229
+ end
230
+
231
+ if @register_method
232
+ cpp.puts "", "#include \"#{@header}\"", ""
233
+ end
234
+
235
+ if @require_custom
236
+ custom_name = "_rbpp_custom.rb.hpp"
237
+ cpp.puts "#include \"#{custom_name}\"" if File.exists?(File.join(@build_dir, custom_name))
238
+ end
239
+
240
+ if @register_includes
241
+ @register_includes.each do |i|
242
+ cpp.puts i
243
+ end
244
+ end
245
+
246
+ if (decls = @declarations.flatten.compact).any?
247
+ cpp.puts "", decls.join("\n"), ""
248
+ end
249
+
250
+ if @register_method
251
+ cpp.puts "#{@register_method}(#{parent_signature}) {"
252
+ end
253
+
254
+ if (regs = @registrations.flatten.compact).any?
255
+ cpp.puts regs.join("\n")
256
+ end
257
+
258
+ if @register_methods
259
+ @register_methods.each do |m|
260
+ cpp.puts m
261
+ end
262
+ end
263
+
264
+ # I really need a better way of handling this
265
+ if @needs_closing
266
+ cpp.puts "}"
267
+ end
268
+ end
118
269
  end
270
+
119
271
  end
120
272
 
273
+ class RbppCustomFileWriter < FileWriter
274
+
275
+ def initialize
276
+ @base_name = "rbpp_custom"
277
+ @header = "_#{@base_name}.rb.hpp"
278
+ @source = "_#{@base_name}.rb.cpp"
279
+ @nodes = []
280
+ @needs_closing = false
281
+ @additional_includes = []
282
+ @require_custom = true
283
+ end
284
+
285
+ def with_includes(includes)
286
+ @additional_includes =
287
+ includes.flatten.inject([]) do |memo, incl|
288
+ memo << "#include \"#{incl}\""; memo
289
+ end
290
+ end
291
+
292
+ protected
293
+
294
+ def write_header
295
+ return unless @registrations.flatten.compact.any?
296
+
297
+ include_guard = "__RICE_GENERATED_#{@base_name}_HPP__"
298
+
299
+ File.open(File.join(@build_dir, @header), "w+") do |hpp|
300
+ hpp.puts "#ifndef #{include_guard}"
301
+ hpp.puts "#define #{include_guard}"
302
+
303
+ if (incls = [@includes, @additional_includes].flatten.compact).any?
304
+ hpp.puts "", incls.uniq.sort.reverse.join("\n"), ""
305
+ end
306
+
307
+ if (decls = @declarations.flatten.compact).any?
308
+ hpp.puts "", decls.join("\n"), ""
309
+ end
310
+ hpp.puts
311
+ hpp.puts "#endif // #{include_guard}"
312
+ end
313
+
314
+ @declarations = []
315
+ @includes = []
316
+ end
317
+
318
+ def write_source
319
+ super if @registrations.flatten.compact.any?
320
+ end
321
+
322
+ end
121
323
 
122
324
  end
123
325
  end
@@ -4,37 +4,59 @@ module RbPlusPlus
4
4
  # one single file
5
5
  class SingleFileWriter < Base
6
6
 
7
+ def initialize(builder, working_dir)
8
+ super
9
+
10
+ @includes = []
11
+ @declarations = []
12
+ @registrations = []
13
+
14
+ # Keep track of the code generated by the global nodes
15
+ @global_hpp = []
16
+ @global_cpp = []
17
+ end
18
+
7
19
  def write
8
20
  process_code(builder)
9
21
 
10
- if Builders::TypesManager.body.length > 0
11
- # Handle to_from_ruby constructions
12
- builder.declarations << Builders::TypesManager.body
13
- end
14
-
15
22
  filename = builder.name
16
23
  cpp_file = File.join(working_dir, "#{filename}.rb.cpp")
17
24
 
18
25
  File.open(cpp_file, "w+") do |cpp|
19
- cpp.puts builder.to_s
26
+
27
+ cpp.puts @includes.flatten.compact.uniq.sort.reverse.join("\n")
28
+ cpp.puts @global_hpp.flatten.compact.join("\n")
29
+ cpp.puts @declarations.flatten.compact.join("\n")
30
+ cpp.puts @global_cpp.flatten.compact.join("\n")
31
+ cpp.puts @registrations.flatten.compact.join("\n")
32
+ cpp.puts "}" # Yeah, need to figure this one out
33
+
20
34
  end
21
35
  end
22
36
 
23
37
  protected
24
38
 
25
39
  # What we do here is to go through the builder heirarchy
26
- # and push all the code from children up to the parent,
40
+ # and push all the code from children up to the parent,
27
41
  # ending up with all the code in the top-level builder
28
42
  def process_code(builder)
29
- builder.builders.each do |b|
30
- process_code(b)
31
- end
43
+ builder.write
32
44
 
33
- return unless builder.parent
45
+ @includes << builder.includes
46
+ @declarations << builder.declarations
47
+ @registrations << builder.registrations
34
48
 
35
- builder.parent.includes << builder.includes
36
- builder.parent.body << builder.body
37
- builder.parent.declarations << builder.declarations
49
+ # Process the globals
50
+ builder.global_nodes.each do |g|
51
+ g.write
52
+ @includes << g.includes
53
+ @global_hpp << g.declarations
54
+ @global_cpp << g.registrations
55
+ end
56
+
57
+ builder.nodes.each do |b|
58
+ process_code(b)
59
+ end
38
60
  end
39
61
 
40
62
  end