wrapture 0.2.2 → 0.3.0
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.
- checksums.yaml +4 -4
- data/bin/wrapture +9 -4
- data/lib/wrapture.rb +24 -1
- data/lib/wrapture/action_spec.rb +81 -0
- data/lib/wrapture/class_spec.rb +359 -192
- data/lib/wrapture/constant_spec.rb +22 -5
- data/lib/wrapture/constants.rb +32 -0
- data/lib/wrapture/errors.rb +57 -0
- data/lib/wrapture/function_spec.rb +207 -36
- data/lib/wrapture/normalize.rb +62 -0
- data/lib/wrapture/rule_spec.rb +87 -0
- data/lib/wrapture/scope.rb +80 -0
- data/lib/wrapture/struct_spec.rb +127 -0
- data/lib/wrapture/version.rb +11 -1
- data/lib/wrapture/wrapped_function_spec.rb +117 -0
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb5e341af7e97543a1ee20d0a4d962f461372c5ef948de704c1508e346ca71c7
|
4
|
+
data.tar.gz: af4cf7f89111e459a866107ebc46823b81d6a4de0bbdd944a3b5294dc0ad9220
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a3e8e31db51f492ab179bc047de225cd7db2ceb7156c1734ce45929cbce325f38abd40d54637c87839d0b0cc2bbf41ec8cf491d128e0a61a01aaafa724c6ef3
|
7
|
+
data.tar.gz: eb13f2975a79f0caf669b3a72408e9af1c61155598ce516c43d406e2b95f3016550724e2efe35766da6ebec0695d8052c2fa9b2149cedad87d0c89eab7672e44
|
data/bin/wrapture
CHANGED
@@ -5,9 +5,14 @@
|
|
5
5
|
require 'yaml'
|
6
6
|
require 'wrapture'
|
7
7
|
|
8
|
-
|
8
|
+
scope = Wrapture::Scope.new
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
ARGV.each do |spec_file|
|
11
|
+
spec = YAML.load_file(spec_file)
|
12
|
+
|
13
|
+
spec['classes'].each do |class_spec|
|
14
|
+
Wrapture::ClassSpec.new(class_spec, scope: scope)
|
15
|
+
end
|
13
16
|
end
|
17
|
+
|
18
|
+
scope.generate_wrappers
|
data/lib/wrapture.rb
CHANGED
@@ -1,10 +1,33 @@
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
2
|
+
|
1
3
|
# frozen_string_literal: true
|
2
4
|
|
3
|
-
|
5
|
+
# Copyright 2019 Joel E. Anderson
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
4
19
|
# Classes and functions for generating language wrappers
|
5
20
|
module Wrapture
|
21
|
+
require 'wrapture/action_spec'
|
6
22
|
require 'wrapture/constant_spec'
|
23
|
+
require 'wrapture/constants'
|
7
24
|
require 'wrapture/class_spec'
|
25
|
+
require 'wrapture/errors'
|
8
26
|
require 'wrapture/function_spec'
|
27
|
+
require 'wrapture/normalize'
|
28
|
+
require 'wrapture/rule_spec'
|
29
|
+
require 'wrapture/scope'
|
30
|
+
require 'wrapture/struct_spec'
|
9
31
|
require 'wrapture/version'
|
32
|
+
require 'wrapture/wrapped_function_spec'
|
10
33
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
# Copyright 2020 Joel E. Anderson
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require 'wrapture/constants'
|
20
|
+
require 'wrapture/errors'
|
21
|
+
|
22
|
+
module Wrapture
|
23
|
+
# An action to take within a generated program.
|
24
|
+
class ActionSpec
|
25
|
+
# Normalizes a hash specification of a rule. Normalization checks for
|
26
|
+
# invalid keys and unrecognized conditions.
|
27
|
+
def self.normalize_spec_hash(spec)
|
28
|
+
normalized = spec.dup
|
29
|
+
|
30
|
+
required_keys = %w[name constructor]
|
31
|
+
|
32
|
+
missing_keys = required_keys - spec.keys
|
33
|
+
unless missing_keys.empty?
|
34
|
+
missing_msg = "required keys are missing: #{missing_keys.join(', ')}"
|
35
|
+
raise(MissingSpecKey, missing_msg)
|
36
|
+
end
|
37
|
+
|
38
|
+
extra_keys = spec.keys - required_keys
|
39
|
+
unless extra_keys.empty?
|
40
|
+
extra_msg = "these keys are unrecognized: #{extra_keys.join(', ')}"
|
41
|
+
raise(InvalidSpecKey, extra_msg)
|
42
|
+
end
|
43
|
+
|
44
|
+
includes = Wrapture.normalize_includes(spec['constructor']['includes'])
|
45
|
+
normalized['constructor']['includes'] = includes
|
46
|
+
|
47
|
+
normalized
|
48
|
+
end
|
49
|
+
|
50
|
+
# Creates an action spec based on the provided spec hash.
|
51
|
+
#
|
52
|
+
# The hash must have the following keys:
|
53
|
+
# name:: the type of action to take (currently only throw-exception is
|
54
|
+
# supported)
|
55
|
+
# constructor:: the function to use to create the exception, described as a
|
56
|
+
# wrapped function call
|
57
|
+
def initialize(spec)
|
58
|
+
@spec = ActionSpec.normalize_spec_hash(spec)
|
59
|
+
end
|
60
|
+
|
61
|
+
# A list of includes needed for the action.
|
62
|
+
def includes
|
63
|
+
@spec['constructor']['includes'].dup
|
64
|
+
end
|
65
|
+
|
66
|
+
# A string containing the invocation of this action.
|
67
|
+
def take
|
68
|
+
call_spec = @spec['constructor']
|
69
|
+
|
70
|
+
params = call_spec['params'].map do |param_spec|
|
71
|
+
if param_spec['value'] == RETURN_VALUE_KEYWORD
|
72
|
+
'return_val'
|
73
|
+
else
|
74
|
+
param_spec['value']
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
"throw #{call_spec['name']}( #{params.join(', ')} )"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/lib/wrapture/class_spec.rb
CHANGED
@@ -1,203 +1,214 @@
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
2
|
+
|
1
3
|
# frozen_string_literal: true
|
2
4
|
|
5
|
+
# Copyright 2019-2020 Joel E. Anderson
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
3
19
|
require 'wrapture/constant_spec'
|
20
|
+
require 'wrapture/constants'
|
4
21
|
require 'wrapture/function_spec'
|
22
|
+
require 'wrapture/normalize'
|
5
23
|
|
6
24
|
module Wrapture
|
7
|
-
##
|
8
25
|
# A description of a class, including its constants, functions, and other
|
9
26
|
# details.
|
10
27
|
class ClassSpec
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
28
|
+
# Normalizes a hash specification of a class. Normalization will check for
|
29
|
+
# things like invalid keys, duplicate entries in include lists, and will set
|
30
|
+
# missing keys to their default values (for example, an empty list if no
|
31
|
+
# includes are given).
|
32
|
+
#
|
33
|
+
# If this spec cannot be normalized, for example because it is invalid or
|
34
|
+
# it uses an unsupported version type, then an exception is raised.
|
35
|
+
def self.normalize_spec_hash(spec)
|
36
|
+
raise NoNamespace unless spec.key?('namespace')
|
18
37
|
|
19
|
-
|
20
|
-
|
38
|
+
normalized = spec.dup
|
39
|
+
normalized.default = []
|
21
40
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
41
|
+
normalized['version'] = Wrapture.spec_version(spec)
|
42
|
+
normalized['includes'] = Wrapture.normalize_includes(spec['includes'])
|
43
|
+
normalized['type'] = ClassSpec.effective_type(normalized)
|
26
44
|
|
27
|
-
|
28
|
-
|
29
|
-
|
45
|
+
if spec.key?('parent')
|
46
|
+
includes = Wrapture.normalize_includes(spec['parent']['includes'])
|
47
|
+
normalized['parent']['includes'] = includes
|
30
48
|
end
|
31
|
-
end
|
32
49
|
|
33
|
-
|
34
|
-
files = []
|
35
|
-
files << generate_declaration_file
|
36
|
-
files << generate_definition_file
|
50
|
+
normalized
|
37
51
|
end
|
38
52
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
when 'equivalent-struct-pointer'
|
44
|
-
equivalent_struct_pointer
|
45
|
-
else
|
46
|
-
param
|
53
|
+
# Gives the effective type of the given class spec hash.
|
54
|
+
def self.effective_type(spec)
|
55
|
+
inferred_pointer_wrapper = spec['constructors'].any? do |func|
|
56
|
+
func['wrapped-function']['return']['type'] == EQUIVALENT_POINTER_KEYWORD
|
47
57
|
end
|
48
|
-
end
|
49
58
|
|
50
|
-
|
51
|
-
|
59
|
+
if spec.key?('type')
|
60
|
+
valid_types = %w[pointer struct]
|
61
|
+
unless valid_types.include?(spec['type'])
|
62
|
+
type_message = "#{spec['type']} is not a valid class type"
|
63
|
+
raise InvalidSpecKey.new(type_message, valid_keys: valid_types)
|
64
|
+
end
|
52
65
|
|
53
|
-
|
54
|
-
|
66
|
+
spec['type']
|
67
|
+
elsif inferred_pointer_wrapper
|
68
|
+
'pointer'
|
69
|
+
else
|
70
|
+
'struct'
|
55
71
|
end
|
56
|
-
|
57
|
-
"#{spec['name']}( #{resolved_params.join ', '} )"
|
58
72
|
end
|
59
73
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
normalized_spec['equivalent-struct']['members'] ||= []
|
65
|
-
normalized_spec['equivalent-struct']['includes'] ||= []
|
66
|
-
|
67
|
-
normalized_spec
|
74
|
+
# Returns a string of the variable with it's type, properly formatted.
|
75
|
+
def self.typed_variable(type, name)
|
76
|
+
"#{type}#{' ' unless type.end_with?('*')}#{name}"
|
68
77
|
end
|
69
78
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
79
|
+
# The underlying struct of this class.
|
80
|
+
attr_reader :struct
|
81
|
+
|
82
|
+
# Creates a class spec based on the provided hash spec.
|
83
|
+
#
|
84
|
+
# The scope can be provided if available.
|
85
|
+
#
|
86
|
+
# The hash must have the following keys:
|
87
|
+
# name:: the name of the class
|
88
|
+
# namespace:: the namespace to put the class into
|
89
|
+
# equivalent-struct:: a hash describing the struct this class wraps
|
90
|
+
#
|
91
|
+
# The following keys are optional:
|
92
|
+
# constructors:: a list of function specs that can create this class
|
93
|
+
# destructor:: a function spec for the destructor of the class
|
94
|
+
# functions:: a list of function specs
|
95
|
+
# constants:: a list of constant specs
|
96
|
+
def initialize(spec, scope: Scope.new)
|
97
|
+
@spec = ClassSpec.normalize_spec_hash(spec)
|
75
98
|
|
76
|
-
|
77
|
-
includes = @spec['equivalent-struct']['includes'].dup
|
99
|
+
@struct = StructSpec.new @spec[EQUIVALENT_STRUCT_KEYWORD]
|
78
100
|
|
79
|
-
@functions.
|
80
|
-
|
81
|
-
|
101
|
+
@functions = @spec['constructors'].map do |constructor_spec|
|
102
|
+
full_spec = constructor_spec.dup
|
103
|
+
full_spec['name'] = @spec['name']
|
104
|
+
full_spec['params'] = constructor_spec['wrapped-function']['params']
|
82
105
|
|
83
|
-
|
84
|
-
includes.concat const.declaration_includes
|
106
|
+
FunctionSpec.new(full_spec, self, constructor: true)
|
85
107
|
end
|
86
108
|
|
87
|
-
|
88
|
-
|
109
|
+
if @spec.key?('destructor')
|
110
|
+
destructor_spec = @spec['destructor'].dup
|
111
|
+
destructor_spec['name'] = "~#{@spec['name']}"
|
89
112
|
|
90
|
-
|
91
|
-
|
113
|
+
@functions << FunctionSpec.new(destructor_spec, self, destructor: true)
|
114
|
+
end
|
92
115
|
|
93
|
-
@functions.each do |
|
94
|
-
|
116
|
+
@spec['functions'].each do |function_spec|
|
117
|
+
@functions << FunctionSpec.new(function_spec, self)
|
95
118
|
end
|
96
119
|
|
97
|
-
@constants.
|
98
|
-
|
120
|
+
@constants = @spec['constants'].map do |constant_spec|
|
121
|
+
ConstantSpec.new(constant_spec)
|
99
122
|
end
|
100
123
|
|
101
|
-
|
124
|
+
scope << self
|
125
|
+
@scope = scope
|
102
126
|
end
|
103
127
|
|
104
|
-
|
105
|
-
|
106
|
-
|
128
|
+
# Returns a cast of an instance of this class to the provided type, if
|
129
|
+
# possible.
|
130
|
+
def cast_to(name, type)
|
131
|
+
struct = "struct #{@struct.name}"
|
107
132
|
|
108
|
-
|
133
|
+
if [EQUIVALENT_STRUCT_KEYWORD, struct].include?(type)
|
134
|
+
equivalent_struct(name)
|
135
|
+
elsif [EQUIVALENT_POINTER_KEYWORD, "#{struct} *"].include?(type)
|
136
|
+
equivalent_struct_pointer(name)
|
109
137
|
end
|
110
|
-
|
111
|
-
false
|
112
138
|
end
|
113
139
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
else
|
118
|
-
"this->equivalent.#{member}"
|
119
|
-
end
|
140
|
+
# The equivalent struct of this class from an instance of it.
|
141
|
+
def equivalent_struct(instance_name)
|
142
|
+
"#{'*' if pointer_wrapper?}#{instance_name}.equivalent"
|
120
143
|
end
|
121
144
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
else
|
126
|
-
'equivalent'
|
127
|
-
end
|
145
|
+
# A pointer to the equivalent struct of this class from an instance of it.
|
146
|
+
def equivalent_struct_pointer(instance_name)
|
147
|
+
"#{'&' unless pointer_wrapper?}#{instance_name}.equivalent"
|
128
148
|
end
|
129
149
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
else
|
134
|
-
'this->equivalent'
|
135
|
-
end
|
150
|
+
# Generates the wrapper class declaration and definition files.
|
151
|
+
def generate_wrappers
|
152
|
+
[generate_declaration_file, generate_definition_file]
|
136
153
|
end
|
137
154
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
else
|
142
|
-
'&this->equivalent'
|
143
|
-
end
|
155
|
+
# The name of the class
|
156
|
+
def name
|
157
|
+
@spec['name']
|
144
158
|
end
|
145
159
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
160
|
+
# True if this class overloads the given one. A class is considered an
|
161
|
+
# overload if its parent is the given class, it has the same equivalent
|
162
|
+
# struct name, and the equivalent struct has a set of rules. The overloaded
|
163
|
+
# class cannot have any rules in its equivalent struct, or it will not be
|
164
|
+
# overloaded.
|
165
|
+
def overloads?(parent_spec)
|
166
|
+
return false unless parent_spec.struct.rules.empty?
|
167
|
+
|
168
|
+
parent_spec.struct.name == struct_name &&
|
169
|
+
parent_spec.name == parent_name &&
|
170
|
+
!@struct.rules.empty?
|
150
171
|
end
|
151
172
|
|
152
|
-
|
153
|
-
|
173
|
+
# The name of the parent of this class, or nil if there is no parent.
|
174
|
+
def parent_name
|
175
|
+
@spec['parent']['name'] if @spec.key?('parent')
|
154
176
|
end
|
155
177
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
yield "#{@spec['name']}::#{wrapped_constructor_signature(index)}{"
|
161
|
-
|
162
|
-
result = resolve_param wrapped_function['return']['type']
|
163
|
-
|
164
|
-
yield " #{result} = #{function_call wrapped_function};"
|
165
|
-
|
166
|
-
yield '}'
|
178
|
+
# The name of the equivalent struct of this class.
|
179
|
+
def struct_name
|
180
|
+
@struct.name
|
167
181
|
end
|
168
182
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
183
|
+
# Gives a code snippet that accesses the equivalent struct from within the
|
184
|
+
# class using the 'this' keyword.
|
185
|
+
def this_struct
|
186
|
+
if pointer_wrapper?
|
187
|
+
'*(this->equivalent)'
|
188
|
+
else
|
189
|
+
'this->equivalent'
|
174
190
|
end
|
175
|
-
|
176
|
-
"#{@spec['name']}( #{params.join ', '} )"
|
177
191
|
end
|
178
192
|
|
179
|
-
|
180
|
-
|
181
|
-
|
193
|
+
# Gives a code snippet that accesses the equivalent struct pointer from
|
194
|
+
# within the class using the 'this' keyword.
|
195
|
+
def this_struct_pointer
|
196
|
+
"#{'&' unless pointer_wrapper?}this->equivalent"
|
182
197
|
end
|
183
198
|
|
184
|
-
|
185
|
-
|
186
|
-
|
199
|
+
# Returns the ClassSpec for the given type in this class's scope.
|
200
|
+
def type(type)
|
201
|
+
@scope.type(type)
|
187
202
|
end
|
188
203
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
File.open(filename, 'w') do |file|
|
193
|
-
declaration_contents do |line|
|
194
|
-
file.puts line
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
filename
|
204
|
+
# Returns true if the given type exists in this class's scope.
|
205
|
+
def type?(type)
|
206
|
+
@scope.type?(type)
|
199
207
|
end
|
200
208
|
|
209
|
+
private
|
210
|
+
|
211
|
+
# Gives the content of the class declaration to a block, line by line.
|
201
212
|
def declaration_contents
|
202
213
|
yield "#ifndef #{header_guard}"
|
203
214
|
yield "#define #{header_guard}"
|
@@ -210,33 +221,32 @@ module Wrapture
|
|
210
221
|
yield
|
211
222
|
yield "namespace #{@spec['namespace']} {"
|
212
223
|
yield
|
213
|
-
|
224
|
+
|
225
|
+
parent = if @spec.key?('parent')
|
226
|
+
": public #{parent_name} "
|
227
|
+
else
|
228
|
+
''
|
229
|
+
end
|
230
|
+
yield " class #{@spec['name']} #{parent}{"
|
231
|
+
|
214
232
|
yield ' public:'
|
215
233
|
|
216
234
|
yield unless @constants.empty?
|
217
235
|
@constants.each do |const|
|
218
|
-
yield "
|
236
|
+
yield " #{const.declaration};"
|
219
237
|
end
|
220
238
|
|
221
239
|
yield
|
222
|
-
|
223
|
-
yield " struct #{struct_name} #{equivalent_name};"
|
240
|
+
yield " #{@struct.declaration equivalent_name};"
|
224
241
|
yield
|
225
242
|
|
226
|
-
|
227
|
-
yield " #{member_constructor_signature};"
|
228
|
-
end
|
243
|
+
member_constructor_declaration { |line| yield " #{line}" }
|
229
244
|
|
230
|
-
|
231
|
-
yield " #{struct_constructor_signature};"
|
232
|
-
yield " #{pointer_constructor_signature};"
|
233
|
-
end
|
245
|
+
pointer_constructor_declaration { |line| yield " #{line}" }
|
234
246
|
|
235
|
-
|
236
|
-
yield " #{wrapped_constructor_signature constructor};"
|
237
|
-
end
|
247
|
+
yield " #{struct_constructor_signature};" unless pointer_wrapper?
|
238
248
|
|
239
|
-
yield " #{
|
249
|
+
overload_declaration { |line| yield " #{line}" }
|
240
250
|
|
241
251
|
@functions.each do |func|
|
242
252
|
yield " #{func.declaration};"
|
@@ -249,18 +259,26 @@ module Wrapture
|
|
249
259
|
yield '#endif' # end of header guard
|
250
260
|
end
|
251
261
|
|
252
|
-
|
253
|
-
|
262
|
+
# A list of includes needed for the declaration of the class.
|
263
|
+
def declaration_includes
|
264
|
+
includes = @spec['includes'].dup
|
254
265
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
266
|
+
includes.concat(@struct.includes)
|
267
|
+
|
268
|
+
@functions.each do |func|
|
269
|
+
includes.concat(func.declaration_includes)
|
259
270
|
end
|
260
271
|
|
261
|
-
|
272
|
+
@constants.each do |const|
|
273
|
+
includes.concat(const.declaration_includes)
|
274
|
+
end
|
275
|
+
|
276
|
+
includes.concat(@spec['parent']['includes']) if @spec.key?('parent')
|
277
|
+
|
278
|
+
includes.uniq
|
262
279
|
end
|
263
280
|
|
281
|
+
# Gives the content of the class definition to a block, line by line.
|
264
282
|
def definition_contents
|
265
283
|
definition_includes.each do |include_file|
|
266
284
|
yield "#include <#{include_file}>"
|
@@ -271,68 +289,217 @@ module Wrapture
|
|
271
289
|
|
272
290
|
yield unless @constants.empty?
|
273
291
|
@constants.each do |const|
|
274
|
-
yield " #{const.definition
|
292
|
+
yield " #{const.definition(@spec['name'])};"
|
275
293
|
end
|
276
294
|
|
277
|
-
|
278
|
-
yield
|
279
|
-
yield " #{@spec['name']}::#{member_constructor_signature} {"
|
295
|
+
member_constructor_definition { |line| yield " #{line}" }
|
280
296
|
|
281
|
-
|
282
|
-
member_decl = equivalent_member member['name']
|
283
|
-
yield " #{member_decl} = #{member['name']};"
|
284
|
-
end
|
285
|
-
|
286
|
-
yield ' }'
|
287
|
-
end
|
297
|
+
pointer_constructor_definition { |line| yield " #{line}" }
|
288
298
|
|
289
299
|
unless pointer_wrapper?
|
290
300
|
yield
|
291
301
|
yield " #{@spec['name']}::#{struct_constructor_signature} {"
|
292
302
|
|
293
|
-
@
|
294
|
-
member_decl =
|
303
|
+
@struct.members.each do |member|
|
304
|
+
member_decl = this_member(member['name'])
|
295
305
|
yield " #{member_decl} = equivalent.#{member['name']};"
|
296
306
|
end
|
297
307
|
|
298
308
|
yield ' }'
|
309
|
+
end
|
310
|
+
|
311
|
+
overload_definition { |line| yield " #{line}" }
|
299
312
|
|
313
|
+
@functions.each do |func|
|
300
314
|
yield
|
301
|
-
yield " #{@spec['name']}::#{pointer_constructor_signature} {"
|
302
315
|
|
303
|
-
@spec['
|
304
|
-
|
305
|
-
yield " #{member_decl} = equivalent->#{member['name']};"
|
316
|
+
func.definition(@spec['name']) do |def_line|
|
317
|
+
yield " #{def_line}"
|
306
318
|
end
|
319
|
+
end
|
307
320
|
|
308
|
-
|
321
|
+
yield
|
322
|
+
yield '}' # end of namespace
|
323
|
+
end
|
324
|
+
|
325
|
+
# A list of includes needed for the definition of the class.
|
326
|
+
def definition_includes
|
327
|
+
includes = ["#{@spec['name']}.hpp"]
|
328
|
+
|
329
|
+
includes.concat(@spec['includes'])
|
330
|
+
|
331
|
+
@functions.each do |func|
|
332
|
+
includes.concat(func.definition_includes)
|
309
333
|
end
|
310
334
|
|
311
|
-
@
|
312
|
-
|
313
|
-
wrapped_constructor_definition(constructor) do |line|
|
314
|
-
yield " #{line}"
|
315
|
-
end
|
335
|
+
@constants.each do |const|
|
336
|
+
includes.concat(const.definition_includes)
|
316
337
|
end
|
317
338
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
339
|
+
includes.concat(overload_definition_includes)
|
340
|
+
|
341
|
+
includes.uniq
|
342
|
+
end
|
343
|
+
|
344
|
+
# Gives the name of the equivalent struct.
|
345
|
+
def equivalent_name
|
346
|
+
"#{'*' if pointer_wrapper?}equivalent"
|
347
|
+
end
|
348
|
+
|
349
|
+
# Generates the declaration of the class.
|
350
|
+
def generate_declaration_file
|
351
|
+
filename = "#{@spec['name']}.hpp"
|
352
|
+
|
353
|
+
File.open(filename, 'w') do |file|
|
354
|
+
declaration_contents do |line|
|
355
|
+
file.puts(line)
|
356
|
+
end
|
324
357
|
end
|
325
358
|
|
326
|
-
|
327
|
-
|
359
|
+
filename
|
360
|
+
end
|
328
361
|
|
329
|
-
|
330
|
-
|
362
|
+
# Generates the definition of the class.
|
363
|
+
def generate_definition_file
|
364
|
+
filename = "#{@spec['name']}.cpp"
|
365
|
+
|
366
|
+
File.open(filename, 'w') do |file|
|
367
|
+
definition_contents do |line|
|
368
|
+
file.puts(line)
|
331
369
|
end
|
332
370
|
end
|
333
371
|
|
372
|
+
filename
|
373
|
+
end
|
374
|
+
|
375
|
+
# The header guard for the class.
|
376
|
+
def header_guard
|
377
|
+
"__#{@spec['name'].upcase}_HPP"
|
378
|
+
end
|
379
|
+
|
380
|
+
# Yields the declaration of the member constructor for a class. This will be
|
381
|
+
# empty if the wrapped struct is a pointer wrapper.
|
382
|
+
def member_constructor_declaration
|
383
|
+
return unless @struct.members?
|
384
|
+
|
385
|
+
yield "#{@spec['name']}( #{@struct.member_list_with_defaults} );"
|
386
|
+
end
|
387
|
+
|
388
|
+
# Yields the definition of the member constructor for a class. This will be
|
389
|
+
# empty if the wrapped struct is a pointer wrapper.
|
390
|
+
def member_constructor_definition
|
391
|
+
return unless @struct.members?
|
392
|
+
|
393
|
+
yield "#{@spec['name']}::#{@spec['name']}( #{@struct.member_list} ) {"
|
394
|
+
|
395
|
+
@struct.members.each do |member|
|
396
|
+
member_decl = this_member(member['name'])
|
397
|
+
yield " #{member_decl} = #{member['name']};"
|
398
|
+
end
|
399
|
+
|
400
|
+
yield '}'
|
401
|
+
end
|
402
|
+
|
403
|
+
# Yields the declaration of the overload function for this class. If there
|
404
|
+
# is no overload function for this class, then nothing is yielded.
|
405
|
+
def overload_declaration
|
406
|
+
return unless @scope.overloads?(self)
|
407
|
+
|
408
|
+
yield "static #{name} *new#{name}( struct #{@struct.name} *equivalent );"
|
409
|
+
end
|
410
|
+
|
411
|
+
# Yields each line of the definition of the overload function, with a
|
412
|
+
# leading empty yield. If there is no overload function for this class,
|
413
|
+
# then nothing is yielded.
|
414
|
+
def overload_definition
|
415
|
+
return unless @scope.overloads?(self)
|
416
|
+
|
334
417
|
yield
|
335
|
-
|
418
|
+
|
419
|
+
parameter = "struct #{@struct.name} *equivalent"
|
420
|
+
yield "#{name} *#{name}::new#{name}( #{parameter} ) {"
|
421
|
+
|
422
|
+
line_prefix = ' '
|
423
|
+
@scope.overloads(self).each do |overload|
|
424
|
+
check = overload.struct.rules_check('equivalent')
|
425
|
+
yield "#{line_prefix}if( #{check} ) {"
|
426
|
+
yield " return new #{overload.name}( equivalent );"
|
427
|
+
line_prefix = ' } else '
|
428
|
+
end
|
429
|
+
|
430
|
+
yield "#{line_prefix}{"
|
431
|
+
yield " return new #{name}( equivalent );"
|
432
|
+
yield ' }'
|
433
|
+
yield '}'
|
434
|
+
end
|
435
|
+
|
436
|
+
# A list of the includes needed for the overload definitions.
|
437
|
+
def overload_definition_includes
|
438
|
+
@scope.overloads(self).map { |overload| "#{overload.name}.hpp" }
|
439
|
+
end
|
440
|
+
|
441
|
+
# Yields the declaration of the pointer constructor for a class.
|
442
|
+
#
|
443
|
+
# If there is already a constructor provided with this signature, then this
|
444
|
+
# function will return with no output.
|
445
|
+
def pointer_constructor_declaration
|
446
|
+
signature_prefix = "#{@spec['name']}( #{@struct.pointer_declaration('')}"
|
447
|
+
return if @functions.any? do |func|
|
448
|
+
func.constructor? && func.signature.start_with?(signature_prefix)
|
449
|
+
end
|
450
|
+
|
451
|
+
yield "#{pointer_constructor_signature};"
|
452
|
+
end
|
453
|
+
|
454
|
+
# Yields the definition of the pointer constructor for a class.
|
455
|
+
#
|
456
|
+
# If there is already a constructor provided with this signature, then this
|
457
|
+
# function will return with no output.
|
458
|
+
#
|
459
|
+
# If this is a pointer wrapper class, then the constructor will simply set
|
460
|
+
# the underlying pointer to the provied one, and return the new object.
|
461
|
+
#
|
462
|
+
# If this is a struct wrapper class, then a constructor will be created that
|
463
|
+
# sets each member of the wrapped struct to the provided value.
|
464
|
+
def pointer_constructor_definition
|
465
|
+
signature_prefix = "#{@spec['name']}( #{@struct.pointer_declaration('')}"
|
466
|
+
return if @functions.any? do |func|
|
467
|
+
func.constructor? && func.signature.start_with?(signature_prefix)
|
468
|
+
end
|
469
|
+
|
470
|
+
yield "#{@spec['name']}::#{pointer_constructor_signature} {"
|
471
|
+
|
472
|
+
if pointer_wrapper?
|
473
|
+
yield ' this->equivalent = equivalent;'
|
474
|
+
else
|
475
|
+
@struct.members.each do |member|
|
476
|
+
member_decl = this_member(member['name'])
|
477
|
+
yield " #{member_decl} = equivalent->#{member['name']};"
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
yield '}'
|
482
|
+
end
|
483
|
+
|
484
|
+
# The signature of the constructor given an equivalent strucct pointer.
|
485
|
+
def pointer_constructor_signature
|
486
|
+
"#{@spec['name']}( #{@struct.pointer_declaration 'equivalent'} )"
|
487
|
+
end
|
488
|
+
|
489
|
+
# Determines if this class is a wrapper for a struct pointer or not.
|
490
|
+
def pointer_wrapper?
|
491
|
+
@spec['type'] == 'pointer'
|
492
|
+
end
|
493
|
+
|
494
|
+
# The signature of the constructor given an equivalent struct type.
|
495
|
+
def struct_constructor_signature
|
496
|
+
"#{@spec['name']}( #{@struct.declaration 'equivalent'} )"
|
497
|
+
end
|
498
|
+
|
499
|
+
# Gives a code snippet that accesses a member of the equivalent struct for
|
500
|
+
# this class within the class using the 'this' keyword.
|
501
|
+
def this_member(member)
|
502
|
+
"this->equivalent#{pointer_wrapper? ? '->' : '.'}#{member}"
|
336
503
|
end
|
337
504
|
end
|
338
505
|
end
|