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 # TODO(vtl): "data" is a pretty vague name. Rename it? | 5 # TODO(vtl): "data" is a pretty vague name. Rename it? |
6 | 6 |
7 import copy | 7 import copy |
8 | 8 |
9 import module as mojom | 9 import module as mojom |
10 | 10 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 test_spec = 'x:' | 58 test_spec = 'x:' |
59 if i > 0: | 59 if i > 0: |
60 test_spec += '.'.join(scope[:i]) + '.' | 60 test_spec += '.'.join(scope[:i]) + '.' |
61 test_spec += name | 61 test_spec += name |
62 kind = kinds.get(test_spec) | 62 kind = kinds.get(test_spec) |
63 if kind: | 63 if kind: |
64 return kind | 64 return kind |
65 | 65 |
66 return kinds.get(spec) | 66 return kinds.get(spec) |
67 | 67 |
68 def LookupConstant(constants, name, scope): | 68 def LookupValue(values, name, scope): |
69 """Like LookupKind, but for constants.""" | 69 """Like LookupKind, but for constant values.""" |
70 for i in xrange(len(scope), -1, -1): | 70 for i in xrange(len(scope), -1, -1): |
71 if i > 0: | 71 if i > 0: |
72 test_spec = '.'.join(scope[:i]) + '.' | 72 test_spec = '.'.join(scope[:i]) + '.' |
73 test_spec += name | 73 test_spec += name |
74 constant = constants.get(test_spec) | 74 value = values.get(test_spec) |
75 if constant: | 75 if value: |
76 return constant | 76 return value |
77 | 77 |
78 return constants.get(name) | 78 return values.get(name) |
79 | 79 |
80 def KindToData(kind): | 80 def KindToData(kind): |
81 return kind.spec | 81 return kind.spec |
82 | 82 |
83 def KindFromData(kinds, data, scope): | 83 def KindFromData(kinds, data, scope): |
84 kind = LookupKind(kinds, data, scope) | 84 kind = LookupKind(kinds, data, scope) |
85 if kind: | 85 if kind: |
86 return kind | 86 return kind |
87 if data.startswith('a:'): | 87 if data.startswith('a:'): |
88 kind = mojom.Array() | 88 kind = mojom.Array() |
(...skipping 18 matching lines...) Expand all Loading... |
107 import_item['module_name'] = import_module.name | 107 import_item['module_name'] = import_module.name |
108 import_item['namespace'] = import_module.namespace | 108 import_item['namespace'] = import_module.namespace |
109 import_item['module'] = import_module | 109 import_item['module'] = import_module |
110 | 110 |
111 # Copy the struct kinds from our imports into the current module. | 111 # Copy the struct kinds from our imports into the current module. |
112 for kind in import_module.kinds.itervalues(): | 112 for kind in import_module.kinds.itervalues(): |
113 if (isinstance(kind, (mojom.Struct, mojom.Enum)) and | 113 if (isinstance(kind, (mojom.Struct, mojom.Enum)) and |
114 kind.imported_from is None): | 114 kind.imported_from is None): |
115 kind = KindFromImport(kind, import_item) | 115 kind = KindFromImport(kind, import_item) |
116 module.kinds[kind.spec] = kind | 116 module.kinds[kind.spec] = kind |
117 # Ditto for constants. | 117 # Ditto for values. |
118 for constant in import_module.constants.itervalues(): | 118 for value in import_module.values.itervalues(): |
119 if constant.imported_from is None: | 119 if value.imported_from is None: |
120 constant = copy.deepcopy(constant) | 120 value = copy.deepcopy(value) |
121 constant.imported_from = import_item | 121 value.imported_from = import_item |
122 module.constants[constant.GetSpec()] = constant | 122 module.values[value.GetSpec()] = value |
123 | 123 |
124 return import_item | 124 return import_item |
125 | 125 |
126 def StructToData(struct): | 126 def StructToData(struct): |
127 return { | 127 return { |
128 istr(0, 'name'): struct.name, | 128 istr(0, 'name'): struct.name, |
129 istr(1, 'fields'): map(FieldToData, struct.fields) | 129 istr(1, 'fields'): map(FieldToData, struct.fields) |
130 } | 130 } |
131 | 131 |
132 def StructFromData(module, data): | 132 def StructFromData(module, data): |
133 struct = mojom.Struct(module=module) | 133 struct = mojom.Struct(module=module) |
134 struct.name = data['name'] | 134 struct.name = data['name'] |
135 struct.attributes = data['attributes'] | 135 struct.attributes = data['attributes'] |
136 struct.spec = 'x:' + module.namespace + '.' + struct.name | 136 struct.spec = 'x:' + module.namespace + '.' + struct.name |
137 module.kinds[struct.spec] = struct | 137 module.kinds[struct.spec] = struct |
138 struct.enums = map(lambda enum: | 138 struct.enums = map(lambda enum: |
139 EnumFromData(module, enum, struct), data['enums']) | 139 EnumFromData(module, enum, struct), data['enums']) |
| 140 struct.constants = map(lambda constant: |
| 141 ConstantFromData(module, constant, struct), data['constants']) |
140 # Stash fields data here temporarily. | 142 # Stash fields data here temporarily. |
141 struct.fields_data = data['fields'] | 143 struct.fields_data = data['fields'] |
142 return struct | 144 return struct |
143 | 145 |
144 def FieldToData(field): | 146 def FieldToData(field): |
145 data = { | 147 data = { |
146 istr(0, 'name'): field.name, | 148 istr(0, 'name'): field.name, |
147 istr(1, 'kind'): KindToData(field.kind) | 149 istr(1, 'kind'): KindToData(field.kind) |
148 } | 150 } |
149 if field.ordinal != None: | 151 if field.ordinal != None: |
150 data[istr(2, 'ordinal')] = field.ordinal | 152 data[istr(2, 'ordinal')] = field.ordinal |
151 if field.default != None: | 153 if field.default != None: |
152 data[istr(3, 'default')] = field.default | 154 data[istr(3, 'default')] = field.default |
153 return data | 155 return data |
154 | 156 |
155 def FixupExpression(module, value, scope): | 157 def FixupExpression(module, value, scope): |
156 if isinstance(value, (tuple, list)): | 158 if isinstance(value, (tuple, list)): |
157 for i in xrange(len(value)): | 159 for i in xrange(len(value)): |
158 if isinstance(value, tuple): | 160 if isinstance(value, tuple): |
159 FixupExpression(module, value[i], scope) | 161 FixupExpression(module, value[i], scope) |
160 else: | 162 else: |
161 value[i] = FixupExpression(module, value[i], scope) | 163 value[i] = FixupExpression(module, value[i], scope) |
162 elif value: | 164 elif value: |
163 constant = LookupConstant(module.constants, value, scope) | 165 result = LookupValue(module.values, value, scope) |
164 if constant: | 166 if result: |
165 return constant | 167 return result |
166 return value | 168 return value |
167 | 169 |
168 def FieldFromData(module, data, struct): | 170 def FieldFromData(module, data, struct): |
169 field = mojom.Field() | 171 field = mojom.Field() |
170 field.name = data['name'] | 172 field.name = data['name'] |
171 field.kind = KindFromData( | 173 field.kind = KindFromData( |
172 module.kinds, data['kind'], (module.namespace, struct.name)) | 174 module.kinds, data['kind'], (module.namespace, struct.name)) |
173 field.ordinal = data.get('ordinal') | 175 field.ordinal = data.get('ordinal') |
174 field.default = FixupExpression( | 176 field.default = FixupExpression( |
175 module, data.get('default'), (module.namespace, struct.name)) | 177 module, data.get('default'), (module.namespace, struct.name)) |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 } | 230 } |
229 | 231 |
230 def InterfaceFromData(module, data): | 232 def InterfaceFromData(module, data): |
231 interface = mojom.Interface(module=module) | 233 interface = mojom.Interface(module=module) |
232 interface.name = data['name'] | 234 interface.name = data['name'] |
233 interface.spec = 'x:' + module.namespace + '.' + interface.name | 235 interface.spec = 'x:' + module.namespace + '.' + interface.name |
234 interface.peer = data['peer'] if data.has_key('peer') else None | 236 interface.peer = data['peer'] if data.has_key('peer') else None |
235 module.kinds[interface.spec] = interface | 237 module.kinds[interface.spec] = interface |
236 interface.enums = map(lambda enum: | 238 interface.enums = map(lambda enum: |
237 EnumFromData(module, enum, interface), data['enums']) | 239 EnumFromData(module, enum, interface), data['enums']) |
| 240 interface.constants = map(lambda constant: |
| 241 ConstantFromData(module, constant, interface), data['constants']) |
238 # Stash methods data here temporarily. | 242 # Stash methods data here temporarily. |
239 interface.methods_data = data['methods'] | 243 interface.methods_data = data['methods'] |
240 return interface | 244 return interface |
241 | 245 |
242 def EnumFieldFromData(module, enum, data, parent_kind): | 246 def EnumFieldFromData(module, enum, data, parent_kind): |
243 field = mojom.EnumField() | 247 field = mojom.EnumField() |
244 field.name = data['name'] | 248 field.name = data['name'] |
| 249 # TODO(mpcomplete): FixupExpression should be done in the second pass, |
| 250 # so constants and enums can refer to each other. |
| 251 # TODO(mpcomplete): But then, what if constants are initialized to an enum? Or |
| 252 # vice versa? |
245 if parent_kind: | 253 if parent_kind: |
246 field.value = FixupExpression( | 254 field.value = FixupExpression( |
247 module, data['value'], (module.namespace, parent_kind.name)) | 255 module, data['value'], (module.namespace, parent_kind.name)) |
248 else: | 256 else: |
249 field.value = FixupExpression( | 257 field.value = FixupExpression( |
250 module, data['value'], (module.namespace, )) | 258 module, data['value'], (module.namespace, )) |
251 constant = mojom.Constant(module, enum, field) | 259 value = mojom.EnumValue(module, enum, field) |
252 module.constants[constant.GetSpec()] = constant | 260 module.values[value.GetSpec()] = value |
253 return field | 261 return field |
254 | 262 |
255 def EnumFromData(module, data, parent_kind): | 263 def EnumFromData(module, data, parent_kind): |
256 enum = mojom.Enum(module=module) | 264 enum = mojom.Enum(module=module) |
257 enum.name = data['name'] | 265 enum.name = data['name'] |
258 name = enum.name | 266 name = enum.name |
259 if parent_kind: | 267 if parent_kind: |
260 name = parent_kind.name + '.' + name | 268 name = parent_kind.name + '.' + name |
261 enum.spec = 'x:%s.%s' % (module.namespace, name) | 269 enum.spec = 'x:%s.%s' % (module.namespace, name) |
262 enum.parent_kind = parent_kind | 270 enum.parent_kind = parent_kind |
263 | 271 |
264 enum.fields = map( | 272 enum.fields = map( |
265 lambda field: EnumFieldFromData(module, enum, field, parent_kind), | 273 lambda field: EnumFieldFromData(module, enum, field, parent_kind), |
266 data['fields']) | 274 data['fields']) |
267 module.kinds[enum.spec] = enum | 275 module.kinds[enum.spec] = enum |
268 return enum | 276 return enum |
269 | 277 |
| 278 def ConstantFromData(module, data, parent_kind): |
| 279 constant = mojom.Constant() |
| 280 constant.name = data['name'] |
| 281 if parent_kind: |
| 282 scope = (module.namespace, parent_kind.name) |
| 283 else: |
| 284 scope = (module.namespace, ) |
| 285 # TODO(mpcomplete): maybe we should only support POD kinds. |
| 286 constant.kind = KindFromData(module.kinds, data['kind'], scope) |
| 287 constant.value = FixupExpression(module, data.get('value'), scope) |
| 288 |
| 289 value = mojom.NamedValue(module, parent_kind, constant.name) |
| 290 module.values[value.GetSpec()] = value |
| 291 return constant |
| 292 |
270 def ModuleToData(module): | 293 def ModuleToData(module): |
271 return { | 294 return { |
272 istr(0, 'name'): module.name, | 295 istr(0, 'name'): module.name, |
273 istr(1, 'namespace'): module.namespace, | 296 istr(1, 'namespace'): module.namespace, |
274 istr(2, 'structs'): map(StructToData, module.structs), | 297 istr(2, 'structs'): map(StructToData, module.structs), |
275 istr(3, 'interfaces'): map(InterfaceToData, module.interfaces) | 298 istr(3, 'interfaces'): map(InterfaceToData, module.interfaces) |
276 } | 299 } |
277 | 300 |
278 def ModuleFromData(data): | 301 def ModuleFromData(data): |
279 module = mojom.Module() | 302 module = mojom.Module() |
280 module.kinds = {} | 303 module.kinds = {} |
281 for kind in mojom.PRIMITIVES: | 304 for kind in mojom.PRIMITIVES: |
282 module.kinds[kind.spec] = kind | 305 module.kinds[kind.spec] = kind |
283 | 306 |
284 module.constants = {} | 307 module.values = {} |
285 | 308 |
286 module.name = data['name'] | 309 module.name = data['name'] |
287 module.namespace = data['namespace'] | 310 module.namespace = data['namespace'] |
288 module.attributes = data['attributes'] | 311 module.attributes = data['attributes'] |
289 # Imports must come first, because they add to module.kinds which is used | 312 # Imports must come first, because they add to module.kinds which is used |
290 # by by the others. | 313 # by by the others. |
291 module.imports = map( | 314 module.imports = map( |
292 lambda import_data: ImportFromData(module, import_data), | 315 lambda import_data: ImportFromData(module, import_data), |
293 data['imports']) | 316 data['imports']) |
294 | 317 |
295 # First pass collects kinds. | 318 # First pass collects kinds. |
296 module.enums = map( | 319 module.enums = map( |
297 lambda enum: EnumFromData(module, enum, None), data['enums']) | 320 lambda enum: EnumFromData(module, enum, None), data['enums']) |
298 module.structs = map( | 321 module.structs = map( |
299 lambda struct: StructFromData(module, struct), data['structs']) | 322 lambda struct: StructFromData(module, struct), data['structs']) |
300 module.interfaces = map( | 323 module.interfaces = map( |
301 lambda interface: InterfaceFromData(module, interface), | 324 lambda interface: InterfaceFromData(module, interface), |
302 data['interfaces']) | 325 data['interfaces']) |
| 326 module.constants = map( |
| 327 lambda constant: ConstantFromData(module, constant, None), |
| 328 data['constants']) |
303 | 329 |
304 # Second pass expands fields and methods. This allows fields and parameters | 330 # Second pass expands fields and methods. This allows fields and parameters |
305 # to refer to kinds defined anywhere in the mojom. | 331 # to refer to kinds defined anywhere in the mojom. |
306 for struct in module.structs: | 332 for struct in module.structs: |
307 struct.fields = map(lambda field: | 333 struct.fields = map(lambda field: |
308 FieldFromData(module, field, struct), struct.fields_data) | 334 FieldFromData(module, field, struct), struct.fields_data) |
309 del struct.fields_data | 335 del struct.fields_data |
310 for interface in module.interfaces: | 336 for interface in module.interfaces: |
311 interface.methods = map(lambda method: | 337 interface.methods = map(lambda method: |
312 MethodFromData(module, method, interface), interface.methods_data) | 338 MethodFromData(module, method, interface), interface.methods_data) |
313 del interface.methods_data | 339 del interface.methods_data |
314 | 340 |
315 return module | 341 return module |
316 | 342 |
317 def OrderedModuleFromData(data): | 343 def OrderedModuleFromData(data): |
318 module = ModuleFromData(data) | 344 module = ModuleFromData(data) |
319 next_interface_ordinal = 0 | 345 next_interface_ordinal = 0 |
320 for interface in module.interfaces: | 346 for interface in module.interfaces: |
321 next_ordinal = 0 | 347 next_ordinal = 0 |
322 for method in interface.methods: | 348 for method in interface.methods: |
323 if method.ordinal is None: | 349 if method.ordinal is None: |
324 method.ordinal = next_ordinal | 350 method.ordinal = next_ordinal |
325 next_ordinal = method.ordinal + 1 | 351 next_ordinal = method.ordinal + 1 |
326 return module | 352 return module |
OLD | NEW |