]> git.saurik.com Git - apple/javascriptcore.git/blob - inspector/scripts/codegen/cpp_generator.py
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / inspector / scripts / codegen / cpp_generator.py
1 #!/usr/bin/env python
2 #
3 # Copyright (c) 2014 Apple Inc. All rights reserved.
4 # Copyright (c) 2014 University of Washington. All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 # 1. Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # 2. Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25 # THE POSSIBILITY OF SUCH DAMAGE.
26
27 import logging
28 import os.path
29 import re
30
31 from generator import ucfirst
32 from models import PrimitiveType, ObjectType, ArrayType, EnumType, AliasedType, Frameworks
33
34 log = logging.getLogger('global')
35
36 _PRIMITIVE_TO_CPP_NAME_MAP = {
37 'boolean': 'bool',
38 'integer': 'int',
39 'number': 'double',
40 'string': 'String',
41 'object': 'Inspector::InspectorObject',
42 'array': 'Inspector::InspectorArray',
43 'any': 'Inspector::InspectorValue'
44 }
45
46 # This class contains extra static methods used for generation, but does
47 # not participate in any inheritance hierarchy. File generators should
48 # extend the generic "Generator" class instead.
49 class CppGenerator:
50
51 # Miscellaneous text manipulation routines.
52 @staticmethod
53 def cpp_getter_method_for_type(_type):
54 if isinstance(_type, ObjectType):
55 return 'getObject'
56 if isinstance(_type, ArrayType):
57 return 'getArray'
58 if isinstance(_type, PrimitiveType):
59 if _type.raw_name() is 'integer':
60 return 'getInteger'
61 elif _type.raw_name() is 'number':
62 return 'getDouble'
63 elif _type.raw_name() is 'any':
64 return 'getValue'
65 else:
66 return 'get' + ucfirst(_type.raw_name())
67 if isinstance(_type, AliasedType):
68 return CppGenerator.cpp_getter_method_for_type(_type.aliased_type)
69 if isinstance(_type, EnumType):
70 return CppGenerator.cpp_getter_method_for_type(_type.primitive_type)
71
72 @staticmethod
73 def cpp_setter_method_for_type(_type):
74 if isinstance(_type, ObjectType):
75 return 'setObject'
76 if isinstance(_type, ArrayType):
77 return 'setArray'
78 if isinstance(_type, PrimitiveType):
79 if _type.raw_name() is 'integer':
80 return 'setInteger'
81 elif _type.raw_name() is 'number':
82 return 'setDouble'
83 elif _type.raw_name() is 'any':
84 return 'setValue'
85 else:
86 return 'set' + ucfirst(_type.raw_name())
87 if isinstance(_type, AliasedType):
88 return CppGenerator.cpp_setter_method_for_type(_type.aliased_type)
89 if isinstance(_type, EnumType):
90 return CppGenerator.cpp_setter_method_for_type(_type.primitive_type)
91
92 # Generate type representations for various situations.
93 @staticmethod
94 def cpp_protocol_type_for_type(_type):
95 if isinstance(_type, ObjectType) and len(_type.members) == 0:
96 return 'Inspector::InspectorObject'
97 if isinstance(_type, ArrayType):
98 if _type.raw_name() is None: # Otherwise, fall through and use typedef'd name.
99 return 'Inspector::Protocol::Array<%s>' % CppGenerator.cpp_protocol_type_for_type(_type.element_type)
100 if isinstance(_type, (ObjectType, AliasedType, EnumType, ArrayType)):
101 return 'Inspector::Protocol::%s::%s' % (_type.type_domain().domain_name, _type.raw_name())
102 if isinstance(_type, PrimitiveType):
103 return CppGenerator.cpp_name_for_primitive_type(_type)
104
105 @staticmethod
106 def cpp_protocol_type_for_type_member(type_member, object_declaration):
107 if isinstance(type_member.type, EnumType) and type_member.type.is_anonymous:
108 return '::'.join([CppGenerator.cpp_protocol_type_for_type(object_declaration.type), ucfirst(type_member.member_name)])
109 else:
110 return CppGenerator.cpp_protocol_type_for_type(type_member.type)
111
112 @staticmethod
113 def cpp_type_for_unchecked_formal_in_parameter(parameter):
114 _type = parameter.type
115 if isinstance(_type, AliasedType):
116 _type = _type.aliased_type # Fall through to enum or primitive.
117
118 if isinstance(_type, EnumType):
119 _type = _type.primitive_type # Fall through to primitive.
120
121 # This handles the 'any' type and objects with defined properties.
122 if isinstance(_type, ObjectType) or _type.qualified_name() is 'object':
123 cpp_name = 'Inspector::InspectorObject'
124 if parameter.is_optional:
125 return 'const %s*' % cpp_name
126 else:
127 return 'const %s&' % cpp_name
128 if isinstance(_type, ArrayType):
129 cpp_name = 'Inspector::InspectorArray'
130 if parameter.is_optional:
131 return 'const %s*' % cpp_name
132 else:
133 return 'const %s&' % cpp_name
134 if isinstance(_type, PrimitiveType):
135 cpp_name = CppGenerator.cpp_name_for_primitive_type(_type)
136 if parameter.is_optional:
137 return 'const %s*' % cpp_name
138 elif _type.raw_name() in ['string']:
139 return 'const %s&' % cpp_name
140 else:
141 return cpp_name
142
143 return "unknown_unchecked_formal_in_parameter_type"
144
145 @staticmethod
146 def cpp_type_for_checked_formal_event_parameter(parameter):
147 return CppGenerator.cpp_type_for_type_with_name(parameter.type, parameter.parameter_name, parameter.is_optional)
148
149 @staticmethod
150 def cpp_type_for_type_member(member):
151 return CppGenerator.cpp_type_for_type_with_name(member.type, member.member_name, False)
152
153 @staticmethod
154 def cpp_type_for_type_with_name(_type, type_name, is_optional):
155 if isinstance(_type, (ArrayType, ObjectType)):
156 return 'RefPtr<%s>' % CppGenerator.cpp_protocol_type_for_type(_type)
157 if isinstance(_type, AliasedType):
158 builder_type = CppGenerator.cpp_protocol_type_for_type(_type)
159 if is_optional:
160 return 'const %s* const' % builder_type
161 elif _type.aliased_type.qualified_name() in ['integer', 'number']:
162 return CppGenerator.cpp_name_for_primitive_type(_type.aliased_type)
163 elif _type.aliased_type.qualified_name() in ['string']:
164 return 'const %s&' % builder_type
165 else:
166 return builder_type
167 if isinstance(_type, PrimitiveType):
168 cpp_name = CppGenerator.cpp_name_for_primitive_type(_type)
169 if _type.qualified_name() in ['object']:
170 return 'RefPtr<Inspector::InspectorObject>'
171 elif _type.qualified_name() in ['any']:
172 return 'RefPtr<Inspector::InspectorValue>'
173 elif is_optional:
174 return 'const %s* const' % cpp_name
175 elif _type.qualified_name() in ['string']:
176 return 'const %s&' % cpp_name
177 else:
178 return cpp_name
179 if isinstance(_type, EnumType):
180 if _type.is_anonymous:
181 enum_type_name = ucfirst(type_name)
182 else:
183 enum_type_name = 'Inspector::Protocol::%s::%s' % (_type.type_domain().domain_name, _type.raw_name())
184
185 if is_optional:
186 return '%s*' % enum_type_name
187 else:
188 return '%s' % enum_type_name
189
190 @staticmethod
191 def cpp_type_for_formal_out_parameter(parameter):
192 _type = parameter.type
193
194 if isinstance(_type, AliasedType):
195 _type = _type.aliased_type # Fall through.
196
197 if isinstance(_type, (ObjectType, ArrayType)):
198 return 'RefPtr<%s>&' % CppGenerator.cpp_protocol_type_for_type(_type)
199 if isinstance(_type, PrimitiveType):
200 cpp_name = CppGenerator.cpp_name_for_primitive_type(_type)
201 if parameter.is_optional:
202 return "Inspector::Protocol::OptOutput<%s>*" % cpp_name
203 else:
204 return '%s*' % cpp_name
205 if isinstance(_type, EnumType):
206 if _type.is_anonymous:
207 return '%sBackendDispatcherHandler::%s*' % (_type.type_domain().domain_name, ucfirst(parameter.parameter_name))
208 else:
209 return 'Inspector::Protocol::%s::%s*' % (_type.type_domain().domain_name, _type.raw_name())
210
211 raise ValueError("unknown formal out parameter type.")
212
213 # FIXME: this is only slightly different from out parameters; they could be unified.
214 @staticmethod
215 def cpp_type_for_formal_async_parameter(parameter):
216 _type = parameter.type
217 if isinstance(_type, AliasedType):
218 _type = _type.aliased_type # Fall through.
219
220 if isinstance(_type, EnumType):
221 _type = _type.primitive_type # Fall through.
222
223 if isinstance(_type, (ObjectType, ArrayType)):
224 return 'RefPtr<%s>&&' % CppGenerator.cpp_protocol_type_for_type(_type)
225 if isinstance(_type, PrimitiveType):
226 cpp_name = CppGenerator.cpp_name_for_primitive_type(_type)
227 if parameter.is_optional:
228 return "Inspector::Protocol::OptOutput<%s>*" % cpp_name
229 elif _type.qualified_name() in ['integer', 'number']:
230 return CppGenerator.cpp_name_for_primitive_type(_type)
231 elif _type.qualified_name() in ['string']:
232 return 'const %s&' % cpp_name
233 else:
234 return cpp_name
235
236 raise ValueError("Unknown formal async parameter type.")
237
238 # In-parameters don't use builder types, because they could be passed
239 # "open types" that are manually constructed out of InspectorObjects.
240
241 # FIXME: Only parameters that are actually open types should need non-builder parameter types.
242 @staticmethod
243 def cpp_type_for_stack_in_parameter(parameter):
244 _type = parameter.type
245 if isinstance(_type, AliasedType):
246 _type = _type.aliased_type # Fall through.
247
248 if isinstance(_type, EnumType):
249 _type = _type.primitive_type # Fall through.
250
251 if isinstance(_type, ObjectType):
252 return "RefPtr<Inspector::InspectorObject>"
253 if isinstance(_type, ArrayType):
254 return "RefPtr<Inspector::InspectorArray>"
255 if isinstance(_type, PrimitiveType):
256 cpp_name = CppGenerator.cpp_name_for_primitive_type(_type)
257 if _type.qualified_name() in ['any', 'object']:
258 return "RefPtr<%s>" % CppGenerator.cpp_name_for_primitive_type(_type)
259 elif parameter.is_optional and _type.qualified_name() not in ['boolean', 'string', 'integer']:
260 return "Inspector::Protocol::OptOutput<%s>" % cpp_name
261 else:
262 return cpp_name
263
264 @staticmethod
265 def cpp_type_for_stack_out_parameter(parameter):
266 _type = parameter.type
267 if isinstance(_type, (ArrayType, ObjectType)):
268 return 'RefPtr<%s>' % CppGenerator.cpp_protocol_type_for_type(_type)
269 if isinstance(_type, AliasedType):
270 builder_type = CppGenerator.cpp_protocol_type_for_type(_type)
271 if parameter.is_optional:
272 return "Inspector::Protocol::OptOutput<%s>" % builder_type
273 return '%s' % builder_type
274 if isinstance(_type, PrimitiveType):
275 cpp_name = CppGenerator.cpp_name_for_primitive_type(_type)
276 if parameter.is_optional:
277 return "Inspector::Protocol::OptOutput<%s>" % cpp_name
278 else:
279 return cpp_name
280 if isinstance(_type, EnumType):
281 if _type.is_anonymous:
282 return '%sBackendDispatcherHandler::%s' % (_type.type_domain().domain_name, ucfirst(parameter.parameter_name))
283 else:
284 return 'Inspector::Protocol::%s::%s' % (_type.type_domain().domain_name, _type.raw_name())
285
286 @staticmethod
287 def cpp_assertion_method_for_type_member(type_member, object_declaration):
288
289 def assertion_method_for_type(_type):
290 return 'BindingTraits<%s>::assertValueHasExpectedType' % CppGenerator.cpp_protocol_type_for_type(_type)
291
292 if isinstance(type_member.type, AliasedType):
293 return assertion_method_for_type(type_member.type.aliased_type)
294 if isinstance(type_member.type, EnumType) and type_member.type.is_anonymous:
295 return 'BindingTraits<%s>::assertValueHasExpectedType' % CppGenerator.cpp_protocol_type_for_type_member(type_member, object_declaration)
296
297 return assertion_method_for_type(type_member.type)
298
299 @staticmethod
300 def cpp_name_for_primitive_type(_type):
301 return _PRIMITIVE_TO_CPP_NAME_MAP.get(_type.raw_name())
302
303 # Decide whether certain helpers are necessary in a situation.
304 @staticmethod
305 def should_use_wrapper_for_return_type(_type):
306 return not isinstance(_type, (ArrayType, ObjectType))
307
308 @staticmethod
309 def should_use_references_for_type(_type):
310 return isinstance(_type, (ArrayType, ObjectType)) or (isinstance(_type, (PrimitiveType)) and _type.qualified_name() in ["any", "object"])
311
312 @staticmethod
313 def should_pass_by_copy_for_return_type(_type):
314 return isinstance(_type, (ArrayType, ObjectType)) or (isinstance(_type, (PrimitiveType)) and _type.qualified_name() == "object")