forked from neuromorphic-paris/tarsier
-
Notifications
You must be signed in to change notification settings - Fork 0
/
template.lua
225 lines (223 loc) · 8.77 KB
/
template.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
local json = (loadfile 'third_party/json.lua/json.lua')()
-- check throws an error if the given variable does not exist or does not have the expected type.
local function check(name, value, expected_type, json_type_name)
if value == nil then
error(name .. ' is not defined')
end
if type(value) ~= expected_type then
error(name .. ' has an incorrect type (expected ' .. json_type_name .. ')')
end
end
return function(configuration_filename)
local configuration_file = io.open(configuration_filename, 'r')
if configuration_file == nil then
error('\'' .. configuration_filename .. '\' could not be open for reading')
end
configuration = json.decode(configuration_file:read('*a'))
configuration_file:close()
if type(configuration) ~= 'table' then
error('\'' .. configuration_filename .. '\' does not contain an object')
end
check(
'\'' .. 'configuration_filename' .. '\'',
configuration,
'table',
'an object')
check(
'\'' .. configuration_filename .. '\'[\'filename\']',
configuration['filename'],
'string',
'a string')
check(
'\'' .. configuration_filename .. '\'[\'name\']',
configuration['name'],
'string',
'a string')
check(
'\'' .. configuration_filename .. '\'[\'description\']',
configuration['description'],
'table',
'an array')
check(
'\'' .. configuration_filename .. '\'[\'template_parameters\']',
configuration['template_parameters'],
'table',
'an array')
check(
'\'' .. configuration_filename .. '\'[\'parameters\']',
configuration['parameters'],
'table',
'an array')
check(
'\'' .. configuration_filename .. '\'[\'input\']',
configuration['input'],
'table',
'an object')
for key, value in pairs(configuration['description']) do
if type(key) ~= 'number' then
error('\'' .. configuration_filename .. '\'[\'description\'] is not an array')
end
check(
'\'' .. configuration_filename .. '\'[\'description\'][' .. tostring(key - 1) .. ']',
value,
'string',
'a string')
end
for key, value in pairs(configuration['template_parameters']) do
if type(key) ~= 'number' then
error('\'' .. configuration_filename .. '\'[\'template_parameters\'] is not an array')
end
local name = '\'' .. configuration_filename .. '\'[\'template_parameters\'][' .. tostring(key - 1) .. ']'
check(
name,
value,
'table',
'an object')
check(
name .. '[\'name\']',
value['name'],
'string',
'a string')
check(
name .. '[\'type\']',
value['type'],
'string',
'a string',
true)
end
for key, value in pairs(configuration['parameters']) do
if type(key) ~= 'number' then
error('\'' .. configuration_filename .. '\'[\'parameters\'] is not an array')
end
local name = '\'' .. configuration_filename .. '\'[\'parameters\'][' .. tostring(key - 1) .. ']'
check(
name,
value,
'table',
'an object')
check(
name .. '[\'name\']',
value['name'],
'string',
'a string')
check(
name .. '[\'type\']',
value['type'],
'string',
'a string')
check(
name .. '[\'store\']',
value['store'],
'string',
'a string')
if value['store'] ~= nil
and value['store'] ~= 'no'
and value['store'] ~= 'mutable'
and value['store'] ~= 'constant'
and value['store'] ~= 'forward' then
error(name .. '[\'store\'] must be one of {\'no\', \'mutable\', \'constant\', \'forward\'}')
end
end
check(
'\'' .. configuration_filename .. '\'[\'input\'][\'name\']',
configuration['input']['name'],
'string',
'a string')
check(
'\'' .. configuration_filename .. '\'[\'input\'][\'type\']',
configuration['input']['type'],
'string',
'a string')
local output_file = io.open(configuration['filename'], 'w')
if output_file == nil then
error('\'' .. configuration['filename'] .. '\' could not be open for writing')
end
local template_parameters = {}
local template_parameters_names = {}
for index, parameter in ipairs(configuration['template_parameters']) do
template_parameters[index] = parameter['type'] .. ' ' .. parameter['name']
template_parameters_names[index] = parameter['name']
end
local parameters = {}
local parameters_names = {}
for index, parameter in ipairs(configuration['parameters']) do
if parameter['store'] == 'forward' then
parameters[index] = parameter['type'] .. '&& ' .. parameter['name']
parameters_names[index] = 'std::forward<' .. parameter['type'] .. '>(' .. parameter['name'] .. ')'
else
parameters[index] = parameter['type'] .. ' ' .. parameter['name']
parameters_names[index] = parameter['name']
end
end
local initialization_parameters = {}
local initialization_parameters_index = 1
local has_initialization_parameters = false
for index, parameter in ipairs(configuration['parameters']) do
if parameter['store'] ~= 'no' then
has_initialization_parameters = true
if parameter['store'] == 'forward' then
initialization_parameters[initialization_parameters_index] = '_' ..
parameter['name'] ..
'(std::forward<' ..
parameter['type'] ..
'>(' ..
parameter['name'] ..
'))'
else
initialization_parameters[initialization_parameters_index] = '_' .. parameter['name'] .. '(' .. parameter['name'] .. ')'
end
initialization_parameters_index = initialization_parameters_index + 1
end
end
output_file:write(
'#pragma once\n\n',
'#include <utility>\n\n',
'/// tarsier is a collection of event handlers.\n',
'namespace tarsier {\n')
for key, value in pairs(configuration['description']) do
output_file:write(' /// ', value, '\n')
end
output_file:write(
' template <', table.concat(template_parameters, ', '), '>\n',
' class ', configuration['name'], ' {\n',
' public:\n',
' ', configuration['name'], '(', table.concat(parameters, ', '), ')')
if has_initialization_parameters then
output_file:write(' :\n',
' ', table.concat(initialization_parameters, ', '))
end
output_file:write(' {\n',
' }\n',
' ', configuration['name'], '(const ', configuration['name'], '&) = delete;\n',
' ', configuration['name'], '(', configuration['name'], '&&) = default;\n',
' ', configuration['name'], '& operator=(const ', configuration['name'], '&) = delete;\n',
' ', configuration['name'], '& operator=(', configuration['name'], '&&) = default;\n',
' virtual ~', configuration['name'], '() {}\n\n',
' /// operator() handles an event.\n',
' virtual void operator()(', configuration['input']['type'], ' ', configuration['input']['name'], ') {\n',
' }\n\n',
' protected:\n')
for index, parameter in ipairs(configuration['parameters']) do
output_file:write(' ')
if parameter['store'] ~= 'no' then
if parameter['store'] == 'constant' then
output_file:write('const ')
end
output_file:write(parameter['type'], ' _', parameter['name'], ';\n')
end
end
output_file:write(' };\n\n',
' /// make_', configuration['name'], ' creates a')
if string.find(configuration['name'], '^\s*[AEIOUaeiou]') then
output_file:write('n')
end
output_file:write(' ', configuration['name'], ' from functors.\n',
' template <', table.concat(template_parameters, ', '), '>\n',
' inline ', configuration['name'], '<', table.concat(template_parameters_names, ', '), '> make_', configuration['name'], '(\n',
' ', table.concat(parameters, ', '), ') {\n',
' return ', configuration['name'], '<', table.concat(template_parameters_names, ', '), '>(\n',
' ', table.concat(parameters_names, ', '), ');\n',
' }\n',
'}\n')
output_file:close()
end