Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: mojo/public/tools/bindings/generators/mojom_cpp_generator.py

Issue 2250183003: Make the fuchsia mojo/public repo the source of truth. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 """Generates C++ source files from a mojom.Module."""
6
7 import mojom.generate.generator as generator
8 import mojom.generate.module as mojom
9 import mojom.generate.pack as pack
10 from mojom.generate.template_expander import UseJinja
11
12
13 _kind_to_cpp_type = {
14 mojom.BOOL: "bool",
15 mojom.INT8: "int8_t",
16 mojom.UINT8: "uint8_t",
17 mojom.INT16: "int16_t",
18 mojom.UINT16: "uint16_t",
19 mojom.INT32: "int32_t",
20 mojom.UINT32: "uint32_t",
21 mojom.FLOAT: "float",
22 mojom.HANDLE: "mojo::Handle",
23 mojom.DCPIPE: "mojo::DataPipeConsumerHandle",
24 mojom.DPPIPE: "mojo::DataPipeProducerHandle",
25 mojom.MSGPIPE: "mojo::MessagePipeHandle",
26 mojom.SHAREDBUFFER: "mojo::SharedBufferHandle",
27 mojom.NULLABLE_HANDLE: "mojo::Handle",
28 mojom.NULLABLE_DCPIPE: "mojo::DataPipeConsumerHandle",
29 mojom.NULLABLE_DPPIPE: "mojo::DataPipeProducerHandle",
30 mojom.NULLABLE_MSGPIPE: "mojo::MessagePipeHandle",
31 mojom.NULLABLE_SHAREDBUFFER: "mojo::SharedBufferHandle",
32 mojom.INT64: "int64_t",
33 mojom.UINT64: "uint64_t",
34 mojom.DOUBLE: "double",
35 }
36
37 _kind_to_cpp_literal_suffix = {
38 mojom.UINT8: "U",
39 mojom.UINT16: "U",
40 mojom.UINT32: "U",
41 mojom.FLOAT: "f",
42 mojom.UINT64: "ULL",
43 }
44
45 def ConstantValue(constant):
46 return ExpressionToText(constant.value, kind=constant.kind)
47
48 def DefaultValue(field):
49 if field.default:
50 if mojom.IsStructKind(field.kind):
51 assert field.default == "default"
52 return "%s::New()" % GetNameForKind(field.kind)
53 return ExpressionToText(field.default, kind=field.kind)
54 return ""
55
56 def IsEnumToken(token):
57 return isinstance(token, mojom.EnumValue)
58
59 def NamespaceToArray(namespace):
60 return namespace.split(".") if namespace else []
61
62 def GetNameForKind(kind, internal = False):
63 parts = []
64 if kind.imported_from:
65 parts.extend(NamespaceToArray(kind.imported_from["namespace"]))
66 if internal:
67 parts.append("internal")
68 if kind.parent_kind:
69 parts.append(kind.parent_kind.name)
70 parts.append(kind.name)
71 return "::".join(parts)
72
73 def GetCppTypeForKind(kind):
74 # TODO(rudominer) After improvements to compiler front end have landed,
75 # revisit strategy used below for emitting a useful error message when an
76 # undefined identifier is referenced.
77 val = _kind_to_cpp_type.get(kind)
78 if (val is not None):
79 return val
80 raise Exception("Unrecognized kind %s" % kind.spec)
81
82 def GetCppType(kind):
83 if mojom.IsArrayKind(kind):
84 return "mojo::internal::Array_Data<%s>*" % GetCppType(kind.kind)
85 if mojom.IsMapKind(kind):
86 return "mojo::internal::Map_Data<%s, %s>*" % (
87 GetCppType(kind.key_kind), GetCppType(kind.value_kind))
88 if mojom.IsStructKind(kind):
89 return "%s_Data*" % GetNameForKind(kind, internal=True)
90 if mojom.IsUnionKind(kind):
91 return "%s_Data" % GetNameForKind(kind, internal=True)
92 if mojom.IsInterfaceKind(kind):
93 return "mojo::internal::Interface_Data"
94 if mojom.IsInterfaceRequestKind(kind):
95 return "mojo::MessagePipeHandle"
96 if mojom.IsEnumKind(kind):
97 return "int32_t"
98 if mojom.IsStringKind(kind):
99 return "mojo::internal::String_Data*"
100 return GetCppTypeForKind(kind)
101
102 def GetCppPodType(kind):
103 if mojom.IsStringKind(kind):
104 return "char*"
105 return GetCppTypeForKind(kind)
106
107 def GetCppArrayArgWrapperType(kind):
108 if mojom.IsEnumKind(kind):
109 return GetNameForKind(kind)
110 if (mojom.IsStructKind(kind) or mojom.IsUnionKind(kind) or
111 mojom.IsInterfaceKind(kind)):
112 return "%sPtr" % GetNameForKind(kind)
113 if mojom.IsArrayKind(kind):
114 return "mojo::Array<%s> " % GetCppArrayArgWrapperType(kind.kind)
115 if mojom.IsMapKind(kind):
116 return "mojo::Map<%s, %s> " % (GetCppArrayArgWrapperType(kind.key_kind),
117 GetCppArrayArgWrapperType(kind.value_kind))
118 if mojom.IsInterfaceRequestKind(kind):
119 return "mojo::InterfaceRequest<%s>" % GetNameForKind(kind.kind)
120 if mojom.IsStringKind(kind):
121 return "mojo::String"
122 if mojom.IsGenericHandleKind(kind):
123 return "mojo::ScopedHandle"
124 if mojom.IsDataPipeConsumerKind(kind):
125 return "mojo::ScopedDataPipeConsumerHandle"
126 if mojom.IsDataPipeProducerKind(kind):
127 return "mojo::ScopedDataPipeProducerHandle"
128 if mojom.IsMessagePipeKind(kind):
129 return "mojo::ScopedMessagePipeHandle"
130 if mojom.IsSharedBufferKind(kind):
131 return "mojo::ScopedSharedBufferHandle"
132 return GetCppTypeForKind(kind)
133
134 def GetCppResultWrapperType(kind):
135 if mojom.IsEnumKind(kind):
136 return GetNameForKind(kind)
137 if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind):
138 return "%sPtr" % GetNameForKind(kind)
139 if mojom.IsArrayKind(kind):
140 return "mojo::Array<%s>" % GetCppArrayArgWrapperType(kind.kind)
141 if mojom.IsMapKind(kind):
142 return "mojo::Map<%s, %s>" % (GetCppArrayArgWrapperType(kind.key_kind),
143 GetCppArrayArgWrapperType(kind.value_kind))
144 if mojom.IsInterfaceKind(kind):
145 return "mojo::InterfaceHandle<%s>" % GetNameForKind(kind)
146 if mojom.IsInterfaceRequestKind(kind):
147 return "mojo::InterfaceRequest<%s>" % GetNameForKind(kind.kind)
148 if mojom.IsStringKind(kind):
149 return "mojo::String"
150 if mojom.IsGenericHandleKind(kind):
151 return "mojo::ScopedHandle"
152 if mojom.IsDataPipeConsumerKind(kind):
153 return "mojo::ScopedDataPipeConsumerHandle"
154 if mojom.IsDataPipeProducerKind(kind):
155 return "mojo::ScopedDataPipeProducerHandle"
156 if mojom.IsMessagePipeKind(kind):
157 return "mojo::ScopedMessagePipeHandle"
158 if mojom.IsSharedBufferKind(kind):
159 return "mojo::ScopedSharedBufferHandle"
160 return GetCppTypeForKind(kind)
161
162 def GetCppWrapperType(kind):
163 if mojom.IsEnumKind(kind):
164 return GetNameForKind(kind)
165 if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind):
166 return "%sPtr" % GetNameForKind(kind)
167 if mojom.IsArrayKind(kind):
168 return "mojo::Array<%s>" % GetCppArrayArgWrapperType(kind.kind)
169 if mojom.IsMapKind(kind):
170 return "mojo::Map<%s, %s>" % (GetCppArrayArgWrapperType(kind.key_kind),
171 GetCppArrayArgWrapperType(kind.value_kind))
172 if mojom.IsInterfaceKind(kind):
173 return "mojo::InterfaceHandle<%s>" % GetNameForKind(kind)
174 if mojom.IsInterfaceRequestKind(kind):
175 return "mojo::InterfaceRequest<%s>" % GetNameForKind(kind.kind)
176 if mojom.IsStringKind(kind):
177 return "mojo::String"
178 if mojom.IsGenericHandleKind(kind):
179 return "mojo::ScopedHandle"
180 if mojom.IsDataPipeConsumerKind(kind):
181 return "mojo::ScopedDataPipeConsumerHandle"
182 if mojom.IsDataPipeProducerKind(kind):
183 return "mojo::ScopedDataPipeProducerHandle"
184 if mojom.IsMessagePipeKind(kind):
185 return "mojo::ScopedMessagePipeHandle"
186 if mojom.IsSharedBufferKind(kind):
187 return "mojo::ScopedSharedBufferHandle"
188 return GetCppTypeForKind(kind)
189
190 def GetCppConstWrapperType(kind):
191 if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind):
192 return "%sPtr" % GetNameForKind(kind)
193 if mojom.IsArrayKind(kind):
194 return "mojo::Array<%s>" % GetCppArrayArgWrapperType(kind.kind)
195 if mojom.IsMapKind(kind):
196 return "mojo::Map<%s, %s>" % (GetCppArrayArgWrapperType(kind.key_kind),
197 GetCppArrayArgWrapperType(kind.value_kind))
198 if mojom.IsInterfaceKind(kind):
199 return "mojo::InterfaceHandle<%s>" % GetNameForKind(kind)
200 if mojom.IsInterfaceRequestKind(kind):
201 return "mojo::InterfaceRequest<%s>" % GetNameForKind(kind.kind)
202 if mojom.IsEnumKind(kind):
203 return GetNameForKind(kind)
204 if mojom.IsStringKind(kind):
205 return "const mojo::String&"
206 if mojom.IsGenericHandleKind(kind):
207 return "mojo::ScopedHandle"
208 if mojom.IsDataPipeConsumerKind(kind):
209 return "mojo::ScopedDataPipeConsumerHandle"
210 if mojom.IsDataPipeProducerKind(kind):
211 return "mojo::ScopedDataPipeProducerHandle"
212 if mojom.IsMessagePipeKind(kind):
213 return "mojo::ScopedMessagePipeHandle"
214 if mojom.IsSharedBufferKind(kind):
215 return "mojo::ScopedSharedBufferHandle"
216 if not kind in _kind_to_cpp_type:
217 print "missing:", kind.spec
218 return GetCppTypeForKind(kind)
219
220 def GetCppFieldType(kind):
221 if mojom.IsStructKind(kind):
222 return ("mojo::internal::StructPointer<%s_Data>" %
223 GetNameForKind(kind, internal=True))
224 if mojom.IsUnionKind(kind):
225 return "%s_Data" % GetNameForKind(kind, internal=True)
226 if mojom.IsArrayKind(kind):
227 return "mojo::internal::ArrayPointer<%s>" % GetCppType(kind.kind)
228 if mojom.IsMapKind(kind):
229 return ("mojo::internal::StructPointer<mojo::internal::Map_Data<%s, %s>>" %
230 (GetCppType(kind.key_kind), GetCppType(kind.value_kind)))
231 if mojom.IsInterfaceKind(kind):
232 return "mojo::internal::Interface_Data"
233 if mojom.IsInterfaceRequestKind(kind):
234 return "mojo::MessagePipeHandle"
235 if mojom.IsEnumKind(kind):
236 return GetNameForKind(kind)
237 if mojom.IsStringKind(kind):
238 return "mojo::internal::StringPointer"
239 return GetCppTypeForKind(kind)
240
241 def GetCppUnionFieldType(kind):
242 if mojom.IsAnyHandleKind(kind):
243 return "MojoHandle"
244 if mojom.IsInterfaceKind(kind):
245 return "uint64_t"
246 if mojom.IsEnumKind(kind):
247 return "int32_t"
248 if mojom.IsUnionKind(kind):
249 return ("mojo::internal::UnionPointer<%s_Data>" %
250 GetNameForKind(kind, internal=True))
251 return GetCppFieldType(kind)
252
253 def GetUnionGetterReturnType(kind):
254 if (mojom.IsStructKind(kind) or mojom.IsUnionKind(kind) or
255 mojom.IsArrayKind(kind) or mojom.IsMapKind(kind) or
256 mojom.IsAnyHandleKind(kind) or mojom.IsInterfaceKind(kind)):
257 return "%s&" % GetCppWrapperType(kind)
258 return GetCppResultWrapperType(kind)
259
260 def TranslateConstants(token, kind):
261 if isinstance(token, mojom.NamedValue):
262 # Both variable and enum constants are constructed like:
263 # Namespace::Struct::CONSTANT_NAME
264 # For enums, CONSTANT_NAME is ENUM_NAME_ENUM_VALUE.
265 name = []
266 if token.imported_from:
267 name.extend(NamespaceToArray(token.namespace))
268 if token.parent_kind:
269 name.append(token.parent_kind.name)
270 if IsEnumToken(token):
271 name.extend([token.enum.name, token.name])
272 else:
273 name.append(token.name)
274
275 ret = "::".join(name)
276
277 # Explicitly disallow cases where we are translating an enum token for a
278 # non-enum (but defined) kind.
279 if IsEnumToken(token) and kind is not None and not mojom.IsEnumKind(kind):
280 raise Exception("Assignment of enum value '%s' to type %s is disallowed" %
281 (ret, _kind_to_cpp_type.get(kind, "<unknown>")))
282
283 # Explicitly disallow a non-enum token for an enum kind, we need an explicit
284 # cast.
285 if not IsEnumToken(token) and mojom.IsEnumKind(kind):
286 raise Exception(
287 "Assignment of non-enum value '%s' to enum-type %s is disallowed" %
288 (ret, GetNameForKind(kind)))
289
290 return ret
291
292 if isinstance(token, mojom.BuiltinValue):
293 if token.value == "double.INFINITY" or token.value == "float.INFINITY":
294 return "INFINITY";
295 if token.value == "double.NEGATIVE_INFINITY" or \
296 token.value == "float.NEGATIVE_INFINITY":
297 return "-INFINITY";
298 if token.value == "double.NAN" or token.value == "float.NAN":
299 return "NAN";
300
301 if (kind is not None and mojom.IsFloatKind(kind)):
302 return token if token.isdigit() else token + "f";
303
304 # Per C++11, 2.14.2, the type of an integer literal is the first of the
305 # corresponding list in Table 6 in which its value can be represented. In this
306 # case, the list for decimal constants with no suffix is:
307 # int, long int, long long int
308 # The standard considers a program ill-formed if it contains an integer
309 # literal that cannot be represented by any of the allowed types.
310 #
311 # As it turns out, MSVC doesn't bother trying to fall back to long long int,
312 # so the integral constant -2147483648 causes it grief: it decides to
313 # represent 2147483648 as an unsigned integer, and then warns that the unary
314 # minus operator doesn't make sense on unsigned types. Doh!
315 if kind == mojom.INT32 and token == "-2147483648":
316 return "(-%d - 1) /* %s */" % (
317 2**31 - 1, "Workaround for MSVC bug; see https://crbug.com/445618")
318
319
320 ret = "%s%s" % (token, _kind_to_cpp_literal_suffix.get(kind, ""))
321
322 # Literal tokens may not be assigned to enum variable. By definition, the
323 # only valid tokens for the RHS of an assignment to an enum named values
324 # (specifically, members of the enumeration).
325 if mojom.IsEnumKind(kind):
326 raise Exception(
327 "Assignment of literal '%s' to enum-type %s is disallowed" %
328 (ret, GetNameForKind(kind)))
329
330 return ret
331
332 def ExpressionToText(value, kind=None):
333 return TranslateConstants(value, kind)
334
335 def ShouldInlineStruct(struct):
336 # TODO(darin): Base this on the size of the wrapper class.
337 if len(struct.fields) > 4:
338 return False
339 for field in struct.fields:
340 if mojom.IsMoveOnlyKind(field.kind):
341 return False
342 return True
343
344 def ShouldInlineUnion(union):
345 return not any(mojom.IsMoveOnlyKind(field.kind) for field in union.fields)
346
347 def GetArrayValidateParamsCtorArgs(kind):
348 if mojom.IsStringKind(kind):
349 expected_num_elements = 0
350 element_is_nullable = False
351 element_validate_params = "nullptr"
352 elif mojom.IsMapKind(kind):
353 expected_num_elements = 0
354 element_is_nullable = mojom.IsNullableKind(kind.value_kind)
355 element_validate_params = GetNewArrayValidateParams(kind.value_kind)
356 else:
357 expected_num_elements = generator.ExpectedArraySize(kind) or 0
358 element_is_nullable = mojom.IsNullableKind(kind.kind)
359 element_validate_params = GetNewArrayValidateParams(kind.kind)
360
361 return "%d, %s, %s" % (expected_num_elements,
362 "true" if element_is_nullable else "false",
363 element_validate_params)
364
365 def GetNewArrayValidateParams(kind):
366 if (not mojom.IsArrayKind(kind) and not mojom.IsMapKind(kind) and
367 not mojom.IsStringKind(kind)):
368 return "nullptr"
369
370 return "new mojo::internal::ArrayValidateParams(%s)" % (
371 GetArrayValidateParamsCtorArgs(kind))
372
373 def GetMapValidateParamsCtorArgs(value_kind):
374 # Unlike GetArrayValidateParams, we are given the wrapped kind, instead of
375 # the raw array kind. So we wrap the return value of GetArrayValidateParams.
376 element_is_nullable = mojom.IsNullableKind(value_kind)
377 return "0, %s, %s" % ("true" if element_is_nullable else "false",
378 GetNewArrayValidateParams(value_kind))
379
380 class Generator(generator.Generator):
381
382 cpp_filters = {
383 "constant_value": ConstantValue,
384 "cpp_const_wrapper_type": GetCppConstWrapperType,
385 "cpp_field_type": GetCppFieldType,
386 "cpp_union_field_type": GetCppUnionFieldType,
387 "cpp_pod_type": GetCppPodType,
388 "cpp_result_type": GetCppResultWrapperType,
389 "cpp_type": GetCppType,
390 "cpp_union_getter_return_type": GetUnionGetterReturnType,
391 "cpp_wrapper_type": GetCppWrapperType,
392 "default_value": DefaultValue,
393 "expression_to_text": ExpressionToText,
394 "get_array_validate_params_ctor_args": GetArrayValidateParamsCtorArgs,
395 "get_map_validate_params_ctor_args": GetMapValidateParamsCtorArgs,
396 "get_name_for_kind": GetNameForKind,
397 "get_pad": pack.GetPad,
398 "has_callbacks": mojom.HasCallbacks,
399 "should_inline": ShouldInlineStruct,
400 "should_inline_union": ShouldInlineUnion,
401 "is_array_kind": mojom.IsArrayKind,
402 "is_cloneable_kind": mojom.IsCloneableKind,
403 "is_enum_kind": mojom.IsEnumKind,
404 "is_integral_kind": mojom.IsIntegralKind,
405 "is_move_only_kind": mojom.IsMoveOnlyKind,
406 "is_any_handle_kind": mojom.IsAnyHandleKind,
407 "is_interface_kind": mojom.IsInterfaceKind,
408 "is_interface_request_kind": mojom.IsInterfaceRequestKind,
409 "is_map_kind": mojom.IsMapKind,
410 "is_nullable_kind": mojom.IsNullableKind,
411 "is_object_kind": mojom.IsObjectKind,
412 "is_string_kind": mojom.IsStringKind,
413 "is_struct_kind": mojom.IsStructKind,
414 "is_union_kind": mojom.IsUnionKind,
415 "struct_size": lambda ps: ps.GetTotalSize() + _HEADER_SIZE,
416 "stylize_method": generator.StudlyCapsToCamel,
417 "to_all_caps": generator.CamelCaseToAllCaps,
418 "under_to_camel": generator.UnderToCamel,
419 }
420
421 def GetJinjaExports(self):
422 return {
423 "module": self.module,
424 "namespace": self.module.namespace,
425 "namespaces_as_array": NamespaceToArray(self.module.namespace),
426 "imports": self.module.imports,
427 "kinds": self.module.kinds,
428 "enums": self.module.enums,
429 "structs": self.GetStructs(),
430 "unions": self.GetUnions(),
431 "interfaces": self.GetInterfaces(),
432 }
433
434 @UseJinja("cpp_templates/module.h.tmpl", filters=cpp_filters)
435 def GenerateModuleHeader(self):
436 return self.GetJinjaExports()
437
438 @UseJinja("cpp_templates/module-internal.h.tmpl", filters=cpp_filters)
439 def GenerateModuleInternalHeader(self):
440 return self.GetJinjaExports()
441
442 @UseJinja("cpp_templates/module-common.h.tmpl", filters=cpp_filters)
443 def GenerateModuleCommonHeader(self):
444 return self.GetJinjaExports()
445
446 @UseJinja("cpp_templates/module-common.cc.tmpl", filters=cpp_filters)
447 def GenerateModuleCommonSource(self):
448 return self.GetJinjaExports()
449
450 @UseJinja("cpp_templates/module-sync.h.tmpl", filters=cpp_filters)
451 def GenerateModuleSynchronousHeader(self):
452 return self.GetJinjaExports()
453
454 @UseJinja("cpp_templates/module-sync.cc.tmpl", filters=cpp_filters)
455 def GenerateModuleSynchronousSource(self):
456 return self.GetJinjaExports()
457
458 @UseJinja("cpp_templates/module.cc.tmpl", filters=cpp_filters)
459 def GenerateModuleSource(self):
460 return self.GetJinjaExports()
461
462 def GenerateFiles(self, args):
463 self.Write(self.GenerateModuleHeader(),
464 self.MatchMojomFilePath("%s.h" % self.module.name))
465 self.Write(self.GenerateModuleInternalHeader(),
466 self.MatchMojomFilePath("%s-internal.h" % self.module.name))
467 self.Write(self.GenerateModuleCommonHeader(),
468 self.MatchMojomFilePath("%s-common.h" % self.module.name))
469 self.Write(self.GenerateModuleCommonSource(),
470 self.MatchMojomFilePath("%s-common.cc" % self.module.name))
471 self.Write(self.GenerateModuleSynchronousHeader(),
472 self.MatchMojomFilePath("%s-sync.h" % self.module.name))
473 self.Write(self.GenerateModuleSynchronousSource(),
474 self.MatchMojomFilePath("%s-sync.cc" % self.module.name))
475 self.Write(self.GenerateModuleSource(),
476 self.MatchMojomFilePath("%s.cc" % self.module.name))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698