]> git.saurik.com Git - apple/javascriptcore.git/blame_incremental - inspector/scripts/codegen/cpp_generator.py
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / inspector / scripts / codegen / cpp_generator.py
... / ...
CommitLineData
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
27import logging
28import os.path
29import re
30
31from generator import ucfirst
32from models import PrimitiveType, ObjectType, ArrayType, EnumType, AliasedType, Frameworks
33
34log = 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.
49class 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")