-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcxx_gen.py
189 lines (164 loc) · 5.23 KB
/
cxx_gen.py
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
def indent(code, **kwargs):
depth = kwargs.get('depth', 1)
ws = ''.join([' ' for d in range(depth)])
if type(code) in (str, unicode):
code = [code]
return [ws + line for line in code]
def gen_system_include(path):
return '#include <{}>'.format(path)
def gen_local_include(path):
return '#include "{}"'.format(path)
def make_const(type_str):
'''Make C++ type const'''
return 'const ' + type_str
def make_ref(type_str, const=True):
'''Make C++ type a reference
If const is True, constify the type'''
if const:
type_str = make_const(type_str)
return type_str + '&'
def gen_arg_list(elems):
if len(elems) == 0:
return ['()']
elif len(elems) == 1:
return ['(' + elems[0] + ')']
else:
code = ['(']
for e in elems[:-1]:
code += indent(e + ',', depth=2)
code += indent(elems[-1] + ')', depth=2)
return code
def gen_applied_arg_list(code, elems):
code = code[:]
args = gen_arg_list(elems)
code[-1] += args[0]
code += args[1:]
return code
# DEPRECATED
#
# TODO(nicholasbishop): fix the users of this method and then remove
# it
def gen_function(return_type, name, args,
static=False, body=None, class_name=None):
qual = 'static ' if static and not body else ''
if body and class_name:
name = class_name + '::' + name
if return_type != '':
return_type += ' '
code = [qual + return_type + name]
code = gen_applied_arg_list(code, args)
if body:
code = gen_block(code, body)
else:
code[-1] += ';'
return code
def gen_func(return_type, name, args, body, static=False, inline=False):
line = ''
if static:
line += 'static '
if inline:
line += 'inline '
if return_type:
line += return_type + ' '
line += name
code = gen_applied_arg_list([line], args)
if body:
code = gen_block(code, body)
else:
code[-1] += ';'
return code
def gen_constructor_definition(class_name, args, body,
initializer_list=None,
scope=None):
code = ['{1}{0}::{0}'.format(
class_name,
scope + '::' if scope else '')]
code = gen_applied_arg_list(code, args)
if initializer_list:
code += indent([': ' + initializer_list])
code = gen_block(code, body)
return code
def gen_block(head, body, trailing_semicolon=False):
code = head[:]
code[-1] += ' {'
code += indent(body)
code += '}'
if trailing_semicolon:
code[-1] += ';'
return code
def _gen_class_or_struct(keyword, name, body, inheritance):
head = keyword + ' ' + name
if inheritance:
head += ' : ' + inheritance
return gen_block([head], body, trailing_semicolon=True)
def gen_class(name, body, inheritance=None):
return _gen_class_or_struct('class', name, body, inheritance)
def gen_struct(name, body, inheritance=None):
return _gen_class_or_struct('struct', name, body, inheritance)
def append_trailing_commas(lines):
"""Return copy of lines with trailing commas appended."""
result = []
for (index, line) in enumerate(lines):
# Append trailing comma if not last line
if (index + 1) != len(lines):
line = '{},'.format(line)
result.append(line)
return result
def gen_enum(name, members, cxx11=False):
head = 'enum '
if cxx11:
head += 'class '
head += name
body = []
for m in members:
# Enum member
line = m[0]
if len(m) == 2:
# Append member value if given
line += ' = {}'.format(m[1])
body.append(line)
return gen_block([head], append_trailing_commas(body),
trailing_semicolon=True)
def gen_namespace(name, body):
return ['namespace ' + name + ' {'] + body + ['}']
def gen_header(guard, body):
return (['// THIS FILE IS AUTOGENERATED',
'#ifndef ' + guard,
'#define ' + guard,
''] +
body +
['', '#endif // ' + guard])
def camel_case_from_underscored(underscored):
result = ''
upcase = True
for c in underscored:
if c == '_':
upcase = True
elif upcase:
upcase = False
result += c.upper()
else:
result += c
return result
def gen_if(condition_block_pairs, else_block=None):
"""Generate a C++ if/else if/else chain
condition_block_pairs is a sequence of pairs, where the first part
of the pair is the conditional and the second part is the block
associated with that condition.
else_block is an optional code block that will cause an else to be
added at the end of the chain.
An exception is thrown if condition_block_pairs is an empty
sequence.
"""
code = []
for pair in condition_block_pairs:
condition = pair[0]
block = pair[1]
prefix = '' if len(code) == 0 else 'else '
control = ['{}if ({})'.format(prefix, condition)]
code += gen_block(control, block)
if not code:
raise Exception('condition_block_pairs is empty')
if else_block:
code += gen_block(['else'], else_block)
return code