| 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 |