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

Side by Side Diff: mojo/public/tools/bindings/pylib/mojom/generate/translate.py

Issue 2888503002: Mojo bindings generator: introduce Stylizer to specify naming rules. (Closed)
Patch Set: Created 3 years, 7 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
1 # Copyright 2013 The Chromium Authors. All rights reserved. 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 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """Convert parse tree to AST. 5 """Convert parse tree to AST.
6 6
7 This module converts the parse tree to the AST we use for code generation. The 7 This module converts the parse tree to the AST we use for code generation. The
8 main entry point is OrderedModule, which gets passed the parser 8 main entry point is OrderedModule, which gets passed the parser
9 representation of a mojom file. When called it's assumed that all imports have 9 representation of a mojom file. When called it's assumed that all imports have
10 already been parsed and converted to ASTs before. 10 already been parsed and converted to ASTs before.
11 """ 11 """
12 12
13 import copy 13 import os
14 import re 14 import re
15 15
16 import module as mojom 16 import module as mojom
17 from mojom.parse import ast 17 from mojom.parse import ast
18 18
19 def _DuplicateName(values): 19 def _DuplicateName(values):
20 """Returns the 'name' of the first entry in |values| whose 'name' has already 20 """Returns the 'mojom_name' of the first entry in |values| whose 'mojom_name'
21 been encountered. If there are no duplicates, returns None.""" 21 has already been encountered. If there are no duplicates, returns None."""
22 names = set() 22 names = set()
23 for value in values: 23 for value in values:
24 if value.name in names: 24 if value.mojom_name in names:
25 return value.name 25 return value.mojom_name
26 names.add(value.name) 26 names.add(value.mojom_name)
27 return None 27 return None
28 28
29 def _ElemsOfType(elems, elem_type, scope): 29 def _ElemsOfType(elems, elem_type, scope):
30 """Find all elements of the given type. 30 """Find all elements of the given type.
31 31
32 Args: 32 Args:
33 elems: {Sequence[Any]} Sequence of elems. 33 elems: {Sequence[Any]} Sequence of elems.
34 elem_type: {Type[C]} Extract all elems of this type. 34 elem_type: {Type[C]} Extract all elems of this type.
35 scope: {str} The name of the surrounding scope (e.g. struct 35 scope: {str} The name of the surrounding scope (e.g. struct
36 definition). Used in error messages. 36 definition). Used in error messages.
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 """Tries to find which Kind a spec refers to, given the scope in which its 114 """Tries to find which Kind a spec refers to, given the scope in which its
115 referenced. Starts checking from the narrowest scope to most general. For 115 referenced. Starts checking from the narrowest scope to most general. For
116 example, given a struct field like 116 example, given a struct field like
117 Foo.Bar x; 117 Foo.Bar x;
118 Foo.Bar could refer to the type 'Bar' in the 'Foo' namespace, or an inner 118 Foo.Bar could refer to the type 'Bar' in the 'Foo' namespace, or an inner
119 type 'Bar' in the struct 'Foo' in the current namespace. 119 type 'Bar' in the struct 'Foo' in the current namespace.
120 120
121 |scope| is a tuple that looks like (namespace, struct/interface), referring 121 |scope| is a tuple that looks like (namespace, struct/interface), referring
122 to the location where the type is referenced.""" 122 to the location where the type is referenced."""
123 if spec.startswith('x:'): 123 if spec.startswith('x:'):
124 name = spec[2:] 124 mojom_name = spec[2:]
125 for i in xrange(len(scope), -1, -1): 125 for i in xrange(len(scope), -1, -1):
126 test_spec = 'x:' 126 test_spec = 'x:'
127 if i > 0: 127 if i > 0:
128 test_spec += '.'.join(scope[:i]) + '.' 128 test_spec += '.'.join(scope[:i]) + '.'
129 test_spec += name 129 test_spec += mojom_name
130 kind = kinds.get(test_spec) 130 kind = kinds.get(test_spec)
131 if kind: 131 if kind:
132 return kind 132 return kind
133 133
134 return kinds.get(spec) 134 return kinds.get(spec)
135 135
136 def _LookupValue(values, name, scope, kind): 136 def _LookupValue(values, mojom_name, scope, kind):
137 """Like LookupKind, but for constant values.""" 137 """Like LookupKind, but for constant values."""
138 # If the type is an enum, the value can be specified as a qualified name, in 138 # If the type is an enum, the value can be specified as a qualified name, in
139 # which case the form EnumName.ENUM_VALUE must be used. We use the presence 139 # which case the form EnumName.ENUM_VALUE must be used. We use the presence
140 # of a '.' in the requested name to identify this. Otherwise, we prepend the 140 # of a '.' in the requested name to identify this. Otherwise, we prepend the
141 # enum name. 141 # enum name.
142 if isinstance(kind, mojom.Enum) and '.' not in name: 142 if isinstance(kind, mojom.Enum) and '.' not in mojom_name:
143 name = '%s.%s' % (kind.spec.split(':', 1)[1], name) 143 mojom_name = '%s.%s' % (kind.spec.split(':', 1)[1], mojom_name)
144 for i in reversed(xrange(len(scope) + 1)): 144 for i in reversed(xrange(len(scope) + 1)):
145 test_spec = '.'.join(scope[:i]) 145 test_spec = '.'.join(scope[:i])
146 if test_spec: 146 if test_spec:
147 test_spec += '.' 147 test_spec += '.'
148 test_spec += name 148 test_spec += mojom_name
149 value = values.get(test_spec) 149 value = values.get(test_spec)
150 if value: 150 if value:
151 return value 151 return value
152 152
153 return values.get(name) 153 return values.get(mojom_name)
154 154
155 def _FixupExpression(module, value, scope, kind): 155 def _FixupExpression(module, value, scope, kind):
156 """Translates an IDENTIFIER into a built-in value or structured NamedValue 156 """Translates an IDENTIFIER into a built-in value or structured NamedValue
157 object.""" 157 object."""
158 if isinstance(value, tuple) and value[0] == 'IDENTIFIER': 158 if isinstance(value, tuple) and value[0] == 'IDENTIFIER':
159 # Allow user defined values to shadow builtins. 159 # Allow user defined values to shadow builtins.
160 result = _LookupValue(module.values, value[1], scope, kind) 160 result = _LookupValue(module.values, value[1], scope, kind)
161 if result: 161 if result:
162 if isinstance(result, tuple): 162 if isinstance(result, tuple):
163 raise Exception('Unable to resolve expression: %r' % value[1]) 163 raise Exception('Unable to resolve expression: %r' % value[1])
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 def _Struct(module, parsed_struct): 239 def _Struct(module, parsed_struct):
240 """ 240 """
241 Args: 241 Args:
242 module: {mojom.Module} Module currently being constructed. 242 module: {mojom.Module} Module currently being constructed.
243 parsed_struct: {ast.Struct} Parsed struct. 243 parsed_struct: {ast.Struct} Parsed struct.
244 244
245 Returns: 245 Returns:
246 {mojom.Struct} AST struct. 246 {mojom.Struct} AST struct.
247 """ 247 """
248 struct = mojom.Struct(module=module) 248 struct = mojom.Struct(module=module)
249 struct.name = parsed_struct.name 249 struct.mojom_name = parsed_struct.mojom_name
250 struct.native_only = parsed_struct.body is None 250 struct.native_only = parsed_struct.body is None
251 struct.spec = 'x:' + module.namespace + '.' + struct.name 251 struct.spec = 'x:' + module.mojom_namespace + '.' + struct.mojom_name
252 module.kinds[struct.spec] = struct 252 module.kinds[struct.spec] = struct
253 if struct.native_only: 253 if struct.native_only:
254 struct.enums = [] 254 struct.enums = []
255 struct.constants = [] 255 struct.constants = []
256 struct.fields_data = [] 256 struct.fields_data = []
257 else: 257 else:
258 struct.enums = map( 258 struct.enums = map(
259 lambda enum: _Enum(module, enum, struct), 259 lambda enum: _Enum(module, enum, struct),
260 _ElemsOfType(parsed_struct.body, ast.Enum, parsed_struct.name)) 260 _ElemsOfType(parsed_struct.body, ast.Enum, parsed_struct.mojom_name))
261 struct.constants = map( 261 struct.constants = map(
262 lambda constant: _Constant(module, constant, struct), 262 lambda constant: _Constant(module, constant, struct),
263 _ElemsOfType(parsed_struct.body, ast.Const, parsed_struct.name)) 263 _ElemsOfType(parsed_struct.body, ast.Const, parsed_struct.mojom_name))
264 # Stash fields parsed_struct here temporarily. 264 # Stash fields parsed_struct here temporarily.
265 struct.fields_data = _ElemsOfType( 265 struct.fields_data = _ElemsOfType(
266 parsed_struct.body, ast.StructField, parsed_struct.name) 266 parsed_struct.body, ast.StructField, parsed_struct.mojom_name)
267 struct.attributes = _AttributeListToDict(parsed_struct.attribute_list) 267 struct.attributes = _AttributeListToDict(parsed_struct.attribute_list)
268 268
269 # Enforce that a [Native] attribute is set to make native-only struct 269 # Enforce that a [Native] attribute is set to make native-only struct
270 # declarations more explicit. 270 # declarations more explicit.
271 if struct.native_only: 271 if struct.native_only:
272 if not struct.attributes or not struct.attributes.get('Native', False): 272 if not struct.attributes or not struct.attributes.get('Native', False):
273 raise Exception("Native-only struct declarations must include a " + 273 raise Exception("Native-only struct declarations must include a " +
274 "Native attribute.") 274 "Native attribute.")
275 275
276 return struct 276 return struct
277 277
278 def _Union(module, parsed_union): 278 def _Union(module, parsed_union):
279 """ 279 """
280 Args: 280 Args:
281 module: {mojom.Module} Module currently being constructed. 281 module: {mojom.Module} Module currently being constructed.
282 parsed_union: {ast.Union} Parsed union. 282 parsed_union: {ast.Union} Parsed union.
283 283
284 Returns: 284 Returns:
285 {mojom.Union} AST union. 285 {mojom.Union} AST union.
286 """ 286 """
287 union = mojom.Union(module=module) 287 union = mojom.Union(module=module)
288 union.name = parsed_union.name 288 union.mojom_name = parsed_union.mojom_name
289 union.spec = 'x:' + module.namespace + '.' + union.name 289 union.spec = 'x:' + module.mojom_namespace + '.' + union.mojom_name
290 module.kinds[union.spec] = union 290 module.kinds[union.spec] = union
291 # Stash fields parsed_union here temporarily. 291 # Stash fields parsed_union here temporarily.
292 union.fields_data = _ElemsOfType( 292 union.fields_data = _ElemsOfType(
293 parsed_union.body, ast.UnionField, parsed_union.name) 293 parsed_union.body, ast.UnionField, parsed_union.mojom_name)
294 union.attributes = _AttributeListToDict(parsed_union.attribute_list) 294 union.attributes = _AttributeListToDict(parsed_union.attribute_list)
295 return union 295 return union
296 296
297 def _StructField(module, parsed_field, struct): 297 def _StructField(module, parsed_field, struct):
298 """ 298 """
299 Args: 299 Args:
300 module: {mojom.Module} Module currently being constructed. 300 module: {mojom.Module} Module currently being constructed.
301 parsed_field: {ast.StructField} Parsed struct field. 301 parsed_field: {ast.StructField} Parsed struct field.
302 struct: {mojom.Struct} Struct this field belongs to. 302 struct: {mojom.Struct} Struct this field belongs to.
303 303
304 Returns: 304 Returns:
305 {mojom.StructField} AST struct field. 305 {mojom.StructField} AST struct field.
306 """ 306 """
307 field = mojom.StructField() 307 field = mojom.StructField()
308 field.name = parsed_field.name 308 field.mojom_name = parsed_field.mojom_name
309 field.kind = _Kind( 309 field.kind = _Kind(
310 module.kinds, _MapKind(parsed_field.typename), 310 module.kinds, _MapKind(parsed_field.typename),
311 (module.namespace, struct.name)) 311 (module.mojom_namespace, struct.mojom_name))
312 field.ordinal = parsed_field.ordinal.value if parsed_field.ordinal else None 312 field.ordinal = parsed_field.ordinal.value if parsed_field.ordinal else None
313 field.default = _FixupExpression( 313 field.default = _FixupExpression(
314 module, parsed_field.default_value, (module.namespace, struct.name), 314 module, parsed_field.default_value,
315 field.kind) 315 (module.mojom_namespace, struct.mojom_name), field.kind)
316 field.attributes = _AttributeListToDict(parsed_field.attribute_list) 316 field.attributes = _AttributeListToDict(parsed_field.attribute_list)
317 return field 317 return field
318 318
319 def _UnionField(module, parsed_field, union): 319 def _UnionField(module, parsed_field, union):
320 """ 320 """
321 Args: 321 Args:
322 module: {mojom.Module} Module currently being constructed. 322 module: {mojom.Module} Module currently being constructed.
323 parsed_field: {ast.UnionField} Parsed union field. 323 parsed_field: {ast.UnionField} Parsed union field.
324 union: {mojom.Union} Union this fields belong to. 324 union: {mojom.Union} Union this fields belong to.
325 325
326 Returns: 326 Returns:
327 {mojom.UnionField} AST union. 327 {mojom.UnionField} AST union.
328 """ 328 """
329 field = mojom.UnionField() 329 field = mojom.UnionField()
330 field.name = parsed_field.name 330 field.mojom_name = parsed_field.mojom_name
331 field.kind = _Kind( 331 field.kind = _Kind(
332 module.kinds, _MapKind(parsed_field.typename), 332 module.kinds, _MapKind(parsed_field.typename),
333 (module.namespace, union.name)) 333 (module.mojom_namespace, union.mojom_name))
334 field.ordinal = parsed_field.ordinal.value if parsed_field.ordinal else None 334 field.ordinal = parsed_field.ordinal.value if parsed_field.ordinal else None
335 field.default = _FixupExpression( 335 field.default = _FixupExpression(
336 module, None, (module.namespace, union.name), field.kind) 336 module, None, (module.mojom_namespace, union.mojom_name), field.kind)
337 field.attributes = _AttributeListToDict(parsed_field.attribute_list) 337 field.attributes = _AttributeListToDict(parsed_field.attribute_list)
338 return field 338 return field
339 339
340 def _Parameter(module, parsed_param, interface): 340 def _Parameter(module, parsed_param, interface):
341 """ 341 """
342 Args: 342 Args:
343 module: {mojom.Module} Module currently being constructed. 343 module: {mojom.Module} Module currently being constructed.
344 parsed_param: {ast.Parameter} Parsed parameter. 344 parsed_param: {ast.Parameter} Parsed parameter.
345 union: {mojom.Interface} Interface this parameter belongs to. 345 union: {mojom.Interface} Interface this parameter belongs to.
346 346
347 Returns: 347 Returns:
348 {mojom.Parameter} AST parameter. 348 {mojom.Parameter} AST parameter.
349 """ 349 """
350 parameter = mojom.Parameter() 350 parameter = mojom.Parameter()
351 parameter.name = parsed_param.name 351 parameter.mojom_name = parsed_param.mojom_name
352 parameter.kind = _Kind( 352 parameter.kind = _Kind(
353 module.kinds, _MapKind(parsed_param.typename), 353 module.kinds, _MapKind(parsed_param.typename),
354 (module.namespace, interface.name)) 354 (module.mojom_namespace, interface.mojom_name))
355 parameter.ordinal = ( 355 parameter.ordinal = (
356 parsed_param.ordinal.value if parsed_param.ordinal else None) 356 parsed_param.ordinal.value if parsed_param.ordinal else None)
357 parameter.default = None # TODO(tibell): We never have these. Remove field? 357 parameter.default = None # TODO(tibell): We never have these. Remove field?
358 parameter.attributes = _AttributeListToDict(parsed_param.attribute_list) 358 parameter.attributes = _AttributeListToDict(parsed_param.attribute_list)
359 return parameter 359 return parameter
360 360
361 def _Method(module, parsed_method, interface): 361 def _Method(module, parsed_method, interface):
362 """ 362 """
363 Args: 363 Args:
364 module: {mojom.Module} Module currently being constructed. 364 module: {mojom.Module} Module currently being constructed.
365 parsed_method: {ast.Method} Parsed method. 365 parsed_method: {ast.Method} Parsed method.
366 interface: {mojom.Interface} Interface this method belongs to. 366 interface: {mojom.Interface} Interface this method belongs to.
367 367
368 Returns: 368 Returns:
369 {mojom.Method} AST method. 369 {mojom.Method} AST method.
370 """ 370 """
371 method = mojom.Method( 371 method = mojom.Method(
372 interface, parsed_method.name, 372 interface, parsed_method.mojom_name,
373 ordinal=parsed_method.ordinal.value if parsed_method.ordinal else None) 373 ordinal=parsed_method.ordinal.value if parsed_method.ordinal else None)
374 method.parameters = map( 374 method.parameters = map(
375 lambda parameter: _Parameter(module, parameter, interface), 375 lambda parameter: _Parameter(module, parameter, interface),
376 parsed_method.parameter_list) 376 parsed_method.parameter_list)
377 if parsed_method.response_parameter_list is not None: 377 if parsed_method.response_parameter_list is not None:
378 method.response_parameters = map( 378 method.response_parameters = map(
379 lambda parameter: _Parameter(module, parameter, interface), 379 lambda parameter: _Parameter(module, parameter, interface),
380 parsed_method.response_parameter_list) 380 parsed_method.response_parameter_list)
381 method.attributes = _AttributeListToDict(parsed_method.attribute_list) 381 method.attributes = _AttributeListToDict(parsed_method.attribute_list)
382 382
383 # Enforce that only methods with response can have a [Sync] attribute. 383 # Enforce that only methods with response can have a [Sync] attribute.
384 if method.sync and method.response_parameters is None: 384 if method.sync and method.response_parameters is None:
385 raise Exception("Only methods with response can include a [Sync] " 385 raise Exception("Only methods with response can include a [Sync] "
386 "attribute. If no response parameters are needed, you " 386 "attribute. If no response parameters are needed, you "
387 "could use an empty response parameter list, i.e., " 387 "could use an empty response parameter list, i.e., "
388 "\"=> ()\".") 388 "\"=> ()\".")
389 389
390 return method 390 return method
391 391
392 def _Interface(module, parsed_iface): 392 def _Interface(module, parsed_iface):
393 """ 393 """
394 Args: 394 Args:
395 module: {mojom.Module} Module currently being constructed. 395 module: {mojom.Module} Module currently being constructed.
396 parsed_iface: {ast.Interface} Parsed interface. 396 parsed_iface: {ast.Interface} Parsed interface.
397 397
398 Returns: 398 Returns:
399 {mojom.Interface} AST interface. 399 {mojom.Interface} AST interface.
400 """ 400 """
401 interface = mojom.Interface(module=module) 401 interface = mojom.Interface(module=module)
402 interface.name = parsed_iface.name 402 interface.mojom_name = parsed_iface.mojom_name
403 interface.spec = 'x:' + module.namespace + '.' + interface.name 403 interface.spec = 'x:' + module.mojom_namespace + '.' + interface.mojom_name
404 module.kinds[interface.spec] = interface 404 module.kinds[interface.spec] = interface
405 interface.enums = map( 405 interface.enums = map(
406 lambda enum: _Enum(module, enum, interface), 406 lambda enum: _Enum(module, enum, interface),
407 _ElemsOfType(parsed_iface.body, ast.Enum, parsed_iface.name)) 407 _ElemsOfType(parsed_iface.body, ast.Enum, parsed_iface.mojom_name))
408 interface.constants = map( 408 interface.constants = map(
409 lambda constant: _Constant(module, constant, interface), 409 lambda constant: _Constant(module, constant, interface),
410 _ElemsOfType(parsed_iface.body, ast.Const, parsed_iface.name)) 410 _ElemsOfType(parsed_iface.body, ast.Const, parsed_iface.mojom_name))
411 # Stash methods parsed_iface here temporarily. 411 # Stash methods parsed_iface here temporarily.
412 interface.methods_data = _ElemsOfType( 412 interface.methods_data = _ElemsOfType(
413 parsed_iface.body, ast.Method, parsed_iface.name) 413 parsed_iface.body, ast.Method, parsed_iface.mojom_name)
414 interface.attributes = _AttributeListToDict(parsed_iface.attribute_list) 414 interface.attributes = _AttributeListToDict(parsed_iface.attribute_list)
415 return interface 415 return interface
416 416
417 def _EnumField(module, enum, parsed_field, parent_kind): 417 def _EnumField(module, enum, parsed_field, parent_kind):
418 """ 418 """
419 Args: 419 Args:
420 module: {mojom.Module} Module currently being constructed. 420 module: {mojom.Module} Module currently being constructed.
421 enum: {mojom.Enum} Enum this field belongs to. 421 enum: {mojom.Enum} Enum this field belongs to.
422 parsed_field: {ast.EnumValue} Parsed enum value. 422 parsed_field: {ast.EnumValue} Parsed enum value.
423 parent_kind: {mojom.Kind} The enclosing type. 423 parent_kind: {mojom.Kind} The enclosing type.
424 424
425 Returns: 425 Returns:
426 {mojom.EnumField} AST enum field. 426 {mojom.EnumField} AST enum field.
427 """ 427 """
428 field = mojom.EnumField() 428 field = mojom.EnumField()
429 field.name = parsed_field.name 429 field.mojom_name = parsed_field.mojom_name
430 # TODO(mpcomplete): FixupExpression should be done in the second pass, 430 # TODO(mpcomplete): FixupExpression should be done in the second pass,
431 # so constants and enums can refer to each other. 431 # so constants and enums can refer to each other.
432 # TODO(mpcomplete): But then, what if constants are initialized to an enum? Or 432 # TODO(mpcomplete): But then, what if constants are initialized to an enum? Or
433 # vice versa? 433 # vice versa?
434 if parent_kind: 434 if parent_kind:
435 field.value = _FixupExpression( 435 field.value = _FixupExpression(
436 module, parsed_field.value, (module.namespace, parent_kind.name), enum) 436 module, parsed_field.value,
437 (module.mojom_namespace, parent_kind.mojom_name), enum)
437 else: 438 else:
438 field.value = _FixupExpression( 439 field.value = _FixupExpression(
439 module, parsed_field.value, (module.namespace, ), enum) 440 module, parsed_field.value, (module.mojom_namespace, ), enum)
440 field.attributes = _AttributeListToDict(parsed_field.attribute_list) 441 field.attributes = _AttributeListToDict(parsed_field.attribute_list)
441 value = mojom.EnumValue(module, enum, field) 442 value = mojom.EnumValue(module, enum, field)
442 module.values[value.GetSpec()] = value 443 module.values[value.GetSpec()] = value
443 return field 444 return field
444 445
445 def _ResolveNumericEnumValues(enum_fields): 446 def _ResolveNumericEnumValues(enum_fields):
446 """ 447 """
447 Given a reference to a list of mojom.EnumField, resolves and assigns their 448 Given a reference to a list of mojom.EnumField, resolves and assigns their
448 values to EnumField.numeric_value. 449 values to EnumField.numeric_value.
449 """ 450 """
450 451
451 # map of <name> -> integral value 452 # map of <mojom_name> -> integral value
452 resolved_enum_values = {} 453 resolved_enum_values = {}
453 prev_value = -1 454 prev_value = -1
454 for field in enum_fields: 455 for field in enum_fields:
455 # This enum value is +1 the previous enum value (e.g: BEGIN). 456 # This enum value is +1 the previous enum value (e.g: BEGIN).
456 if field.value is None: 457 if field.value is None:
457 prev_value += 1 458 prev_value += 1
458 459
459 # Integral value (e.g: BEGIN = -0x1). 460 # Integral value (e.g: BEGIN = -0x1).
460 elif type(field.value) is str: 461 elif type(field.value) is str:
461 prev_value = int(field.value, 0) 462 prev_value = int(field.value, 0)
462 463
463 # Reference to a previous enum value (e.g: INIT = BEGIN). 464 # Reference to a previous enum value (e.g: INIT = BEGIN).
464 elif type(field.value) is mojom.EnumValue: 465 elif type(field.value) is mojom.EnumValue:
465 prev_value = resolved_enum_values[field.value.name] 466 prev_value = resolved_enum_values[field.value.mojom_name]
466 else: 467 else:
467 raise Exception("Unresolved enum value.") 468 raise Exception("Unresolved enum value.")
468 469
469 resolved_enum_values[field.name] = prev_value 470 resolved_enum_values[field.mojom_name] = prev_value
470 field.numeric_value = prev_value 471 field.numeric_value = prev_value
471 472
472 def _Enum(module, parsed_enum, parent_kind): 473 def _Enum(module, parsed_enum, parent_kind):
473 """ 474 """
474 Args: 475 Args:
475 module: {mojom.Module} Module currently being constructed. 476 module: {mojom.Module} Module currently being constructed.
476 parsed_enum: {ast.Enum} Parsed enum. 477 parsed_enum: {ast.Enum} Parsed enum.
477 478
478 Returns: 479 Returns:
479 {mojom.Enum} AST enum. 480 {mojom.Enum} AST enum.
480 """ 481 """
481 enum = mojom.Enum(module=module) 482 enum = mojom.Enum(module=module)
482 enum.name = parsed_enum.name 483 enum.mojom_name = parsed_enum.mojom_name
483 enum.native_only = parsed_enum.enum_value_list is None 484 enum.native_only = parsed_enum.enum_value_list is None
484 name = enum.name 485 mojom_name = enum.mojom_name
485 if parent_kind: 486 if parent_kind:
486 name = parent_kind.name + '.' + name 487 mojom_name = parent_kind.mojom_name + '.' + mojom_name
487 enum.spec = 'x:%s.%s' % (module.namespace, name) 488 enum.spec = 'x:%s.%s' % (module.mojom_namespace, mojom_name)
488 enum.parent_kind = parent_kind 489 enum.parent_kind = parent_kind
489 enum.attributes = _AttributeListToDict(parsed_enum.attribute_list) 490 enum.attributes = _AttributeListToDict(parsed_enum.attribute_list)
490 if enum.native_only: 491 if enum.native_only:
491 enum.fields = [] 492 enum.fields = []
492 else: 493 else:
493 enum.fields = map( 494 enum.fields = map(
494 lambda field: _EnumField(module, enum, field, parent_kind), 495 lambda field: _EnumField(module, enum, field, parent_kind),
495 parsed_enum.enum_value_list) 496 parsed_enum.enum_value_list)
496 _ResolveNumericEnumValues(enum.fields) 497 _ResolveNumericEnumValues(enum.fields)
497 498
(...skipping 11 matching lines...) Expand all
509 def _Constant(module, parsed_const, parent_kind): 510 def _Constant(module, parsed_const, parent_kind):
510 """ 511 """
511 Args: 512 Args:
512 module: {mojom.Module} Module currently being constructed. 513 module: {mojom.Module} Module currently being constructed.
513 parsed_const: {ast.Const} Parsed constant. 514 parsed_const: {ast.Const} Parsed constant.
514 515
515 Returns: 516 Returns:
516 {mojom.Constant} AST constant. 517 {mojom.Constant} AST constant.
517 """ 518 """
518 constant = mojom.Constant() 519 constant = mojom.Constant()
519 constant.name = parsed_const.name 520 constant.mojom_name = parsed_const.mojom_name
520 if parent_kind: 521 if parent_kind:
521 scope = (module.namespace, parent_kind.name) 522 scope = (module.mojom_namespace, parent_kind.mojom_name)
522 else: 523 else:
523 scope = (module.namespace, ) 524 scope = (module.mojom_namespace, )
524 # TODO(mpcomplete): maybe we should only support POD kinds. 525 # TODO(mpcomplete): maybe we should only support POD kinds.
525 constant.kind = _Kind(module.kinds, _MapKind(parsed_const.typename), scope) 526 constant.kind = _Kind(module.kinds, _MapKind(parsed_const.typename), scope)
526 constant.parent_kind = parent_kind 527 constant.parent_kind = parent_kind
527 constant.value = _FixupExpression(module, parsed_const.value, scope, None) 528 constant.value = _FixupExpression(module, parsed_const.value, scope, None)
528 529
529 value = mojom.ConstantValue(module, parent_kind, constant) 530 value = mojom.ConstantValue(module, parent_kind, constant)
530 module.values[value.GetSpec()] = value 531 module.values[value.GetSpec()] = value
531 return constant 532 return constant
532 533
533 def _Module(tree, name, imports): 534 def _Module(tree, path, imports):
534 """ 535 """
535 Args: 536 Args:
536 tree: {ast.Mojom} The parse tree. 537 tree: {ast.Mojom} The parse tree.
537 name: {str} The mojom filename, excluding the path. 538 path: {str} The path to the mojom file.
538 imports: {Dict[str, mojom.Module]} Mapping from filenames, as they appear in 539 imports: {Dict[str, mojom.Module]} Mapping from filenames, as they appear in
539 the import list, to already processed modules. Used to process imports. 540 the import list, to already processed modules. Used to process imports.
540 541
541 Returns: 542 Returns:
542 {mojom.Module} An AST for the mojom. 543 {mojom.Module} An AST for the mojom.
543 """ 544 """
544 module = mojom.Module() 545 module = mojom.Module(path=path)
545 module.kinds = {} 546 module.kinds = {}
546 for kind in mojom.PRIMITIVES: 547 for kind in mojom.PRIMITIVES:
547 module.kinds[kind.spec] = kind 548 module.kinds[kind.spec] = kind
548 549
549 module.values = {} 550 module.values = {}
550 551
551 module.name = name 552 module.mojom_namespace = tree.module.mojom_namespace[1] if tree.module else ''
552 module.namespace = tree.module.name[1] if tree.module else ''
553 # Imports must come first, because they add to module.kinds which is used 553 # Imports must come first, because they add to module.kinds which is used
554 # by by the others. 554 # by by the others.
555 module.imports = [ 555 module.imports = [
556 _Import(module, imports[imp.import_filename]) 556 _Import(module, imports[imp.import_filename])
557 for imp in tree.import_list] 557 for imp in tree.import_list]
558 if tree.module and tree.module.attribute_list: 558 if tree.module and tree.module.attribute_list:
559 assert isinstance(tree.module.attribute_list, ast.AttributeList) 559 assert isinstance(tree.module.attribute_list, ast.AttributeList)
560 # TODO(vtl): Check for duplicate keys here. 560 # TODO(vtl): Check for duplicate keys here.
561 module.attributes = dict((attribute.key, attribute.value) 561 module.attributes = dict((attribute.key, attribute.value)
562 for attribute in tree.module.attribute_list) 562 for attribute in tree.module.attribute_list)
563 563
564 filename = os.path.basename(path)
564 # First pass collects kinds. 565 # First pass collects kinds.
565 module.enums = map( 566 module.enums = map(
566 lambda enum: _Enum(module, enum, None), 567 lambda enum: _Enum(module, enum, None),
567 _ElemsOfType(tree.definition_list, ast.Enum, name)) 568 _ElemsOfType(tree.definition_list, ast.Enum, filename))
568 module.structs = map( 569 module.structs = map(
569 lambda struct: _Struct(module, struct), 570 lambda struct: _Struct(module, struct),
570 _ElemsOfType(tree.definition_list, ast.Struct, name)) 571 _ElemsOfType(tree.definition_list, ast.Struct, filename))
571 module.unions = map( 572 module.unions = map(
572 lambda union: _Union(module, union), 573 lambda union: _Union(module, union),
573 _ElemsOfType(tree.definition_list, ast.Union, name)) 574 _ElemsOfType(tree.definition_list, ast.Union, filename))
574 module.interfaces = map( 575 module.interfaces = map(
575 lambda interface: _Interface(module, interface), 576 lambda interface: _Interface(module, interface),
576 _ElemsOfType(tree.definition_list, ast.Interface, name)) 577 _ElemsOfType(tree.definition_list, ast.Interface, filename))
577 module.constants = map( 578 module.constants = map(
578 lambda constant: _Constant(module, constant, None), 579 lambda constant: _Constant(module, constant, None),
579 _ElemsOfType(tree.definition_list, ast.Const, name)) 580 _ElemsOfType(tree.definition_list, ast.Const, filename))
580 581
581 # Second pass expands fields and methods. This allows fields and parameters 582 # Second pass expands fields and methods. This allows fields and parameters
582 # to refer to kinds defined anywhere in the mojom. 583 # to refer to kinds defined anywhere in the mojom.
583 for struct in module.structs: 584 for struct in module.structs:
584 struct.fields = map(lambda field: 585 struct.fields = map(lambda field:
585 _StructField(module, field, struct), struct.fields_data) 586 _StructField(module, field, struct), struct.fields_data)
586 del struct.fields_data 587 del struct.fields_data
587 for union in module.unions: 588 for union in module.unions:
588 union.fields = map(lambda field: 589 union.fields = map(lambda field:
589 _UnionField(module, field, union), union.fields_data) 590 _UnionField(module, field, union), union.fields_data)
590 del union.fields_data 591 del union.fields_data
591 for interface in module.interfaces: 592 for interface in module.interfaces:
592 interface.methods = map(lambda method: 593 interface.methods = map(lambda method:
593 _Method(module, method, interface), interface.methods_data) 594 _Method(module, method, interface), interface.methods_data)
594 del interface.methods_data 595 del interface.methods_data
595 596
596 return module 597 return module
597 598
598 def OrderedModule(tree, name, imports): 599 def OrderedModule(tree, path, imports):
599 """Convert parse tree to AST module. 600 """Convert parse tree to AST module.
600 601
601 Args: 602 Args:
602 tree: {ast.Mojom} The parse tree. 603 tree: {ast.Mojom} The parse tree.
603 name: {str} The mojom filename, excluding the path. 604 path: {str} The path to the mojom file.
604 imports: {Dict[str, mojom.Module]} Mapping from filenames, as they appear in 605 imports: {Dict[str, mojom.Module]} Mapping from filenames, as they appear in
605 the import list, to already processed modules. Used to process imports. 606 the import list, to already processed modules. Used to process imports.
606 607
607 Returns: 608 Returns:
608 {mojom.Module} An AST for the mojom. 609 {mojom.Module} An AST for the mojom.
609 """ 610 """
610 module = _Module(tree, name, imports) 611 module = _Module(tree, path, imports)
611 return module 612 return module
OLDNEW
« no previous file with comments | « mojo/public/tools/bindings/pylib/mojom/generate/module.py ('k') | mojo/public/tools/bindings/pylib/mojom/parse/ast.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698