OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |