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,77 +1,70 @@
|
|
1
1
|
module RbGCCXML
|
2
|
-
class Node
|
3
|
-
|
2
|
+
class Node
|
3
|
+
|
4
|
+
# Specify to Rb++ that this node is not to be wrapped
|
4
5
|
def ignore
|
5
|
-
|
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
|
-
#
|
14
|
+
|
15
|
+
# Has this node been previously declared to not be wrapped?
|
9
16
|
def ignored?
|
10
|
-
|
17
|
+
!!cache[:ignored]
|
11
18
|
end
|
12
19
|
|
13
20
|
# Specifies that this node has been included somewhere else
|
14
|
-
def
|
15
|
-
|
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
|
-
|
27
|
+
cache[:wrap_as] = name
|
21
28
|
self
|
22
29
|
end
|
23
|
-
|
24
|
-
#
|
25
|
-
def
|
26
|
-
|
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
|
-
|
38
|
+
!!cache[:wrap_as]
|
32
39
|
end
|
33
40
|
|
34
|
-
alias_method :
|
35
|
-
def
|
36
|
-
|
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
|
-
|
41
|
-
|
42
|
-
nodes = rbgccxml_classes(*args)
|
43
|
-
return cache(nodes)
|
45
|
+
|
46
|
+
def cpp_name
|
47
|
+
rbgccxml_name
|
44
48
|
end
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
53
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
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
|
-
|
4
|
-
|
5
|
-
|
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
|
-
|
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
|
-
|
9
|
-
|
10
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
19
|
-
|
70
|
+
new_file_for(self.builder)
|
71
|
+
process_globals(self.builder)
|
20
72
|
|
21
|
-
@
|
73
|
+
@global_writer.with_includes(self.builder.additional_includes)
|
74
|
+
@global_writer.write(@build_dir)
|
22
75
|
|
23
|
-
|
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
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
37
|
-
|
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
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
-
|
82
|
-
|
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
|
-
|
89
|
-
|
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
|
-
|
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(
|
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
|
-
|
102
|
-
|
103
|
-
hpp.puts "
|
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
|
-
|
216
|
+
if @register_method
|
217
|
+
hpp.puts "#{@register_method}(#{parent_signature});"
|
218
|
+
end
|
108
219
|
|
109
|
-
|
110
|
-
"
|
111
|
-
|
112
|
-
"}"
|
113
|
-
]
|
220
|
+
hpp.puts
|
221
|
+
hpp.puts "#endif // #{include_guard}"
|
222
|
+
end
|
114
223
|
end
|
115
224
|
|
116
|
-
|
117
|
-
|
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
|
-
|
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.
|
30
|
-
process_code(b)
|
31
|
-
end
|
43
|
+
builder.write
|
32
44
|
|
33
|
-
|
45
|
+
@includes << builder.includes
|
46
|
+
@declarations << builder.declarations
|
47
|
+
@registrations << builder.registrations
|
34
48
|
|
35
|
-
|
36
|
-
builder.
|
37
|
-
|
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
|