1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved. 24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# found in the LICENSE file. 44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 50529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch# TODO(vtl): "data" is a pretty vague name. Rename it? 60529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)import copy 84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 90529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochimport module as mojom 100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch# This module provides a mechanism to turn mojom Modules to dictionaries and 124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# back again. This can be used to persist a mojom Module created progromatically 134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# or to read a dictionary from code or a file. 144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# Example: 154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# test_dict = { 164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# 'name': 'test', 174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# 'namespace': 'testspace', 184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# 'structs': [{ 194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# 'name': 'teststruct', 204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# 'fields': [ 214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# {'name': 'testfield1', 'kind': 'i32'}, 224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# {'name': 'testfield2', 'kind': 'a:i32', 'ordinal': 42}]}], 234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# 'interfaces': [{ 244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# 'name': 'Server', 254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# 'methods': [{ 264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# 'name': 'Foo', 274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# 'parameters': [{ 284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# 'name': 'foo', 'kind': 'i32'}, 294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# {'name': 'bar', 'kind': 'a:x:teststruct'}], 304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# 'ordinal': 42}]}] 314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# } 320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch# test_module = data.ModuleFromData(test_dict) 334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# Used to create a subclass of str that supports sorting by index, to make 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)# pretty printing maintain the order. 364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def istr(index, string): 374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) class IndexedString(str): 384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) def __lt__(self, other): 394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return self.__index__ < other.__index__ 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rv = IndexedString(string) 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rv.__index__ = index 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return rv 444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibuiltin_values = frozenset([ 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "double.INFINITY", 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "double.NEGATIVE_INFINITY", 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "double.NAN", 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "float.INFINITY", 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "float.NEGATIVE_INFINITY", 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci "float.NAN"]) 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccidef IsBuiltinValue(value): 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return value in builtin_values 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)def LookupKind(kinds, spec, scope): 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) """Tries to find which Kind a spec refers to, given the scope in which its 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) referenced. Starts checking from the narrowest scope to most general. For 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) example, given a struct field like 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Foo.Bar x; 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Foo.Bar could refer to the type 'Bar' in the 'Foo' namespace, or an inner 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) type 'Bar' in the struct 'Foo' in the current namespace. 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) |scope| is a tuple that looks like (namespace, struct/interface), referring 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) to the location where the type is referenced.""" 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if spec.startswith('x:'): 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) name = spec[2:] 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for i in xrange(len(scope), -1, -1): 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) test_spec = 'x:' 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if i > 0: 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) test_spec += '.'.join(scope[:i]) + '.' 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) test_spec += name 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) kind = kinds.get(test_spec) 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if kind: 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return kind 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return kinds.get(spec) 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 79116680a4aac90f2aa7413d9095a592090648e557Ben Murdochdef LookupValue(values, name, scope, kind): 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Like LookupKind, but for constant values.""" 81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch # If the type is an enum, the value can be specified as a qualified name, in 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch # which case the form EnumName.ENUM_VALUE must be used. We use the presence 83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch # of a '.' in the requested name to identify this. Otherwise, we prepend the 84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch # enum name. 85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if isinstance(kind, mojom.Enum) and '.' not in name: 86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch name = '%s.%s' % (kind.spec.split(':', 1)[1], name) 87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for i in reversed(xrange(len(scope) + 1)): 88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch test_spec = '.'.join(scope[:i]) 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if test_spec: 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch test_spec += '.' 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) test_spec += name 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) value = values.get(test_spec) 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if value: 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return value 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return values.get(name) 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdochdef FixupExpression(module, value, scope, kind): 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci """Translates an IDENTIFIER into a built-in value or structured NamedValue 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci object.""" 10146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if isinstance(value, tuple) and value[0] == 'IDENTIFIER': 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # Allow user defined values to shadow builtins. 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch result = LookupValue(module.values, value[1], scope, kind) 10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if result: 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if isinstance(result, tuple): 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci raise Exception('Unable to resolve expression: %r' % value[1]) 10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return result 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if IsBuiltinValue(value[1]): 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return mojom.BuiltinValue(value[1]) 11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return value 11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def KindToData(kind): 1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return kind.spec 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)def KindFromData(kinds, data, scope): 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) kind = LookupKind(kinds, data, scope) 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if kind: 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return kind 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if data.startswith('?'): 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kind = KindFromData(kinds, data[1:], scope).MakeNullableKind() 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif data.startswith('a:'): 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kind = mojom.Array(KindFromData(kinds, data[2:], scope)) 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) elif data.startswith('r:'): 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kind = mojom.InterfaceRequest(KindFromData(kinds, data[2:], scope)) 126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch elif data.startswith('a'): 127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch colon = data.find(':') 128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch length = int(data[1:colon]) 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kind = mojom.FixedArray(length, KindFromData(kinds, data[colon+1:], scope)) 1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) else: 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kind = mojom.Kind(data) 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) kinds[data] = kind 1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return kind 1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)def KindFromImport(original_kind, imported_from): 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) """Used with 'import module' - clones the kind imported from the given 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) module's namespace. Only used with Structs, Interfaces and Enums.""" 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kind = copy.copy(original_kind) 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # |shared_definition| is used to store various properties (see 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # |AddSharedProperty()| in module.py), including |imported_from|. We don't 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # want the copy to share these with the original, so copy it if necessary. 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if hasattr(original_kind, 'shared_definition'): 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kind.shared_definition = copy.copy(original_kind.shared_definition) 145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) kind.imported_from = imported_from 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return kind 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def ImportFromData(module, data): 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) import_module = data['module'] 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) import_item = {} 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) import_item['module_name'] = import_module.name 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) import_item['namespace'] = import_module.namespace 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) import_item['module'] = import_module 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # Copy the struct kinds from our imports into the current module. 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for kind in import_module.kinds.itervalues(): 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (isinstance(kind, (mojom.Struct, mojom.Enum, mojom.Interface)) and 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) kind.imported_from is None): 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) kind = KindFromImport(kind, import_item) 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) module.kinds[kind.spec] = kind 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # Ditto for values. 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for value in import_module.values.itervalues(): 164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if value.imported_from is None: 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # Values don't have shared definitions (since they're not nullable), so no 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci # need to do anything special. 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci value = copy.copy(value) 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) value.imported_from = import_item 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) module.values[value.GetSpec()] = value 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return import_item 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def StructToData(struct): 1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return { 1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) istr(0, 'name'): struct.name, 1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) istr(1, 'fields'): map(FieldToData, struct.fields) 1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def StructFromData(module, data): 1805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu struct = mojom.Struct(module=module) 1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) struct.name = data['name'] 182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) struct.attributes = data['attributes'] 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) struct.spec = 'x:' + module.namespace + '.' + struct.name 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) module.kinds[struct.spec] = struct 185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) struct.enums = map(lambda enum: 186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EnumFromData(module, enum, struct), data['enums']) 187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) struct.constants = map(lambda constant: 188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ConstantFromData(module, constant, struct), data['constants']) 1890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch # Stash fields data here temporarily. 1900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch struct.fields_data = data['fields'] 1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return struct 1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def FieldToData(field): 1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data = { 1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) istr(0, 'name'): field.name, 1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) istr(1, 'kind'): KindToData(field.kind) 1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if field.ordinal != None: 1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data[istr(2, 'ordinal')] = field.ordinal 2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if field.default != None: 2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data[istr(3, 'default')] = field.default 2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return data 2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)def FieldFromData(module, data, struct): 2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) field = mojom.Field() 2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) field.name = data['name'] 207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) field.kind = KindFromData( 208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) module.kinds, data['kind'], (module.namespace, struct.name)) 2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) field.ordinal = data.get('ordinal') 210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) field.default = FixupExpression( 211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch module, data.get('default'), (module.namespace, struct.name), field.kind) 2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return field 2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def ParameterToData(parameter): 2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data = { 2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) istr(0, 'name'): parameter.name, 2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) istr(1, 'kind'): parameter.kind.spec 2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if parameter.ordinal != None: 2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data[istr(2, 'ordinal')] = parameter.ordinal 2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if parameter.default != None: 2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data[istr(3, 'default')] = parameter.default 2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return data 2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)def ParameterFromData(module, data, interface): 2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) parameter = mojom.Parameter() 2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) parameter.name = data['name'] 228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) parameter.kind = KindFromData( 229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) module.kinds, data['kind'], (module.namespace, interface.name)) 2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) parameter.ordinal = data.get('ordinal') 2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) parameter.default = data.get('default') 2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return parameter 2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def MethodToData(method): 2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data = { 2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) istr(0, 'name'): method.name, 2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) istr(1, 'parameters'): map(ParameterToData, method.parameters) 2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if method.ordinal != None: 2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data[istr(2, 'ordinal')] = method.ordinal 241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if method.response_parameters != None: 242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) data[istr(3, 'response_parameters')] = map( 243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ParameterToData, method.response_parameters) 2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return data 2454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)def MethodFromData(module, data, interface): 247010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) method = mojom.Method(interface, data['name'], ordinal=data.get('ordinal')) 2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) method.default = data.get('default') 249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) method.parameters = map(lambda parameter: 250a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ParameterFromData(module, parameter, interface), data['parameters']) 251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if data.has_key('response_parameters'): 252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) method.response_parameters = map( 253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) lambda parameter: ParameterFromData(module, parameter, interface), 254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) data['response_parameters']) 2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return method 2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def InterfaceToData(interface): 2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return { 2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) istr(0, 'name'): interface.name, 2600de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) istr(1, 'client'): interface.client, 261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) istr(2, 'methods'): map(MethodToData, interface.methods) 2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def InterfaceFromData(module, data): 2655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu interface = mojom.Interface(module=module) 2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) interface.name = data['name'] 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) interface.spec = 'x:' + module.namespace + '.' + interface.name 2680de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) interface.client = data['client'] if data.has_key('client') else None 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) module.kinds[interface.spec] = interface 270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) interface.enums = map(lambda enum: 271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EnumFromData(module, enum, interface), data['enums']) 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) interface.constants = map(lambda constant: 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ConstantFromData(module, constant, interface), data['constants']) 2740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch # Stash methods data here temporarily. 2750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch interface.methods_data = data['methods'] 2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return interface 2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)def EnumFieldFromData(module, enum, data, parent_kind): 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) field = mojom.EnumField() 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) field.name = data['name'] 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # TODO(mpcomplete): FixupExpression should be done in the second pass, 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # so constants and enums can refer to each other. 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # TODO(mpcomplete): But then, what if constants are initialized to an enum? Or 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # vice versa? 285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if parent_kind: 286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) field.value = FixupExpression( 287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch module, data['value'], (module.namespace, parent_kind.name), enum) 288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) else: 289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) field.value = FixupExpression( 290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch module, data['value'], (module.namespace, ), enum) 291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) value = mojom.EnumValue(module, enum, field) 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) module.values[value.GetSpec()] = value 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return field 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)def EnumFromData(module, data, parent_kind): 2965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu enum = mojom.Enum(module=module) 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enum.name = data['name'] 298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) name = enum.name 299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if parent_kind: 300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) name = parent_kind.name + '.' + name 301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) enum.spec = 'x:%s.%s' % (module.namespace, name) 302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) enum.parent_kind = parent_kind 303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enum.fields = map( 305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) lambda field: EnumFieldFromData(module, enum, field, parent_kind), 306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) data['fields']) 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) module.kinds[enum.spec] = enum 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return enum 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)def ConstantFromData(module, data, parent_kind): 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) constant = mojom.Constant() 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) constant.name = data['name'] 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if parent_kind: 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scope = (module.namespace, parent_kind.name) 315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else: 316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scope = (module.namespace, ) 317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) # TODO(mpcomplete): maybe we should only support POD kinds. 318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) constant.kind = KindFromData(module.kinds, data['kind'], scope) 319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch constant.value = FixupExpression(module, data.get('value'), scope, None) 320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci value = mojom.ConstantValue(module, parent_kind, constant) 322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) module.values[value.GetSpec()] = value 323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return constant 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def ModuleToData(module): 3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return { 3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) istr(0, 'name'): module.name, 3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) istr(1, 'namespace'): module.namespace, 3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) istr(2, 'structs'): map(StructToData, module.structs), 3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) istr(3, 'interfaces'): map(InterfaceToData, module.interfaces) 3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def ModuleFromData(data): 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) module = mojom.Module() 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) module.kinds = {} 3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for kind in mojom.PRIMITIVES: 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) module.kinds[kind.spec] = kind 3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) module.values = {} 340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) module.name = data['name'] 3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) module.namespace = data['namespace'] 343010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) module.attributes = data['attributes'] 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # Imports must come first, because they add to module.kinds which is used 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # by by the others. 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) module.imports = map( 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) lambda import_data: ImportFromData(module, import_data), 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) data['imports']) 3490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch # First pass collects kinds. 351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) module.enums = map( 352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) lambda enum: EnumFromData(module, enum, None), data['enums']) 3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) module.structs = map( 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) lambda struct: StructFromData(module, struct), data['structs']) 3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) module.interfaces = map( 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) lambda interface: InterfaceFromData(module, interface), 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) data['interfaces']) 358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) module.constants = map( 359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) lambda constant: ConstantFromData(module, constant, None), 360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data['constants']) 361a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch # Second pass expands fields and methods. This allows fields and parameters 3630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch # to refer to kinds defined anywhere in the mojom. 3640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for struct in module.structs: 3650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch struct.fields = map(lambda field: 3660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FieldFromData(module, field, struct), struct.fields_data) 3670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch del struct.fields_data 3680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for interface in module.interfaces: 3690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch interface.methods = map(lambda method: 3700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch MethodFromData(module, method, interface), interface.methods_data) 3710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch del interface.methods_data 3720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return module 3744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 375f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)def OrderedModuleFromData(data): 376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) module = ModuleFromData(data) 377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for interface in module.interfaces: 378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) next_ordinal = 0 379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for method in interface.methods: 380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if method.ordinal is None: 381f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) method.ordinal = next_ordinal 382f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) next_ordinal = method.ordinal + 1 383f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return module 384