OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2016 The Chromium Authors. All rights reserved. | 2 # Copyright 2016 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 import math | 6 import math |
7 import sys | 7 import sys |
8 | 8 |
9 import json5_generator | 9 import json5_generator |
10 import template_expander | 10 import template_expander |
11 import make_style_builder | 11 import make_style_builder |
12 | 12 |
13 from name_utilities import ( | 13 from name_utilities import ( |
14 enum_for_css_keyword, enum_type_name, enum_value_name, class_member_name, me thod_name, | 14 enum_for_css_keyword, enum_type_name, enum_value_name, class_member_name, me thod_name, |
15 class_name, join_name | 15 class_name, join_name |
16 ) | 16 ) |
17 from collections import defaultdict, OrderedDict | 17 from collections import defaultdict, OrderedDict |
18 from itertools import chain | 18 from itertools import chain |
19 | 19 |
20 # Heuristic ordering of types from largest to smallest, used to sort fields by t heir alignment sizes. | 20 # Heuristic ordering of types from largest to smallest, used to sort fields by t heir alignment sizes. |
21 # Specifying the exact alignment sizes for each type is impossible because it's platform specific, | 21 # Specifying the exact alignment sizes for each type is impossible because it's platform specific, |
22 # so we define an ordering instead. | 22 # so we define an ordering instead. |
23 # The ordering comes from the data obtained in: | 23 # The ordering comes from the data obtained in: |
24 # https://codereview.chromium.org/2841413002 | 24 # https://codereview.chromium.org/2841413002 |
25 # TODO(shend): Put alignment sizes into code form, rather than linking to a CL w hich may disappear. | 25 # TODO(shend): Put alignment sizes into code form, rather than linking to a CL w hich may disappear. |
26 ALIGNMENT_ORDER = [ | 26 ALIGNMENT_ORDER = [ |
27 'double', | 27 'double', |
28 'Font', 'FillLayer', 'NinePieceImage', # Aligns like a void * (can be 32 or 64 bits) | 28 'AtomicString', 'RefPtr', 'Persistent', 'Font', 'FillLayer', 'NinePieceImage ', # Aligns like a pointer (can be 32 or 64 bits) |
29 'LengthBox', 'LengthSize', 'Length', 'float', | 29 'LengthBox', 'LengthSize', 'Length', 'TextSizeAdjust', 'TabSize', 'float', |
30 'StyleColor', 'Color', 'unsigned', 'int', | 30 'StyleColor', 'Color', 'unsigned', 'int', |
31 'short', | 31 'short', |
32 'char', | 32 'uint8_t', 'char', |
33 'bool' | 33 'bool' |
34 ] | 34 ] |
35 | 35 |
36 # TODO(shend): Improve documentation and add docstrings. | 36 # TODO(shend): Improve documentation and add docstrings. |
37 | 37 |
38 | 38 |
39 def _flatten_list(x): | 39 def _flatten_list(x): |
40 """Flattens a list of lists into a single list.""" | 40 """Flattens a list of lists into a single list.""" |
41 return list(chain.from_iterable(x)) | 41 return list(chain.from_iterable(x)) |
42 | 42 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
103 | 103 |
104 Attributes: | 104 Attributes: |
105 field_role: The semantic role of the field. Can be: | 105 field_role: The semantic role of the field. Can be: |
106 - 'property': for fields that store CSS properties | 106 - 'property': for fields that store CSS properties |
107 - 'inherited_flag': for single-bit flags that store whether a proper ty is | 107 - 'inherited_flag': for single-bit flags that store whether a proper ty is |
108 inherited by this style or set explicitly | 108 inherited by this style or set explicitly |
109 name_for_methods: String used to form the names of getters and setters. | 109 name_for_methods: String used to form the names of getters and setters. |
110 Should be in upper camel case. | 110 Should be in upper camel case. |
111 property_name: Name of the property that the field is part of. | 111 property_name: Name of the property that the field is part of. |
112 type_name: Name of the C++ type exposed by the generated interface (e.g. EClear, int). | 112 type_name: Name of the C++ type exposed by the generated interface (e.g. EClear, int). |
113 pointer_type_name: Name of the pointer type that wraps this field (e.g. RefPtr). | |
meade_UTC10
2017/05/23 04:49:52
nit: Should it be "wrapper_pointer_name" or simila
shend
2017/05/23 23:20:58
done.
| |
113 field_template: Determines the interface generated for the field. Can be one of: | 114 field_template: Determines the interface generated for the field. Can be one of: |
114 keyword, flag, or monotonic_flag. | 115 keyword, flag, or monotonic_flag. |
115 field_group: The name of the group that this field is inside. | 116 field_group: The name of the group that this field is inside. |
116 size: Number of bits needed for storage. | 117 size: Number of bits needed for storage. |
117 default_value: Default value for this field when it is first initialized . | 118 default_value: Default value for this field when it is first initialized . |
118 """ | 119 """ |
119 | 120 |
120 def __init__(self, field_role, name_for_methods, property_name, type_name, | 121 def __init__(self, field_role, name_for_methods, property_name, type_name, p ointer_type_name, |
121 field_template, field_group, size, default_value, has_custom_co mpare_and_copy, | 122 field_template, field_group, size, default_value, has_custom_co mpare_and_copy, |
122 getter_method_name, setter_method_name, initial_method_name, ** kwargs): | 123 getter_method_name, setter_method_name, initial_method_name, ** kwargs): |
123 """Creates a new field.""" | 124 """Creates a new field.""" |
124 self.name = class_member_name(name_for_methods) | 125 self.name = class_member_name(name_for_methods) |
125 self.property_name = property_name | 126 self.property_name = property_name |
126 self.type_name = type_name | 127 self.type_name = type_name |
128 self.pointer_type_name = pointer_type_name | |
129 self.alignment_type = self.pointer_type_name or self.type_name | |
127 self.field_template = field_template | 130 self.field_template = field_template |
128 self.group_name = field_group | 131 self.group_name = field_group |
129 self.group_member_name = class_member_name(join_name(field_group, 'data' )) if field_group else None | 132 self.group_member_name = class_member_name(join_name(field_group, 'data' )) if field_group else None |
130 self.size = size | 133 self.size = size |
131 self.default_value = default_value | 134 self.default_value = default_value |
132 self.has_custom_compare_and_copy = has_custom_compare_and_copy | 135 self.has_custom_compare_and_copy = has_custom_compare_and_copy |
133 | 136 |
134 # Field role: one of these must be true | 137 # Field role: one of these must be true |
135 self.is_property = field_role == 'property' | 138 self.is_property = field_role == 'property' |
136 self.is_inherited_flag = field_role == 'inherited_flag' | 139 self.is_inherited_flag = field_role == 'inherited_flag' |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
265 elif property_['field_template'] == 'primitive': | 268 elif property_['field_template'] == 'primitive': |
266 type_name = property_['type_name'] | 269 type_name = property_['type_name'] |
267 default_value = property_['default_value'] | 270 default_value = property_['default_value'] |
268 size = 1 if type_name == 'bool' else None # pack bools with 1 bit. | 271 size = 1 if type_name == 'bool' else None # pack bools with 1 bit. |
269 else: | 272 else: |
270 assert property_['field_template'] in ('monotonic_flag',) | 273 assert property_['field_template'] in ('monotonic_flag',) |
271 type_name = 'bool' | 274 type_name = 'bool' |
272 default_value = 'false' | 275 default_value = 'false' |
273 size = 1 | 276 size = 1 |
274 | 277 |
278 if property_['pointer_type_name']: | |
279 assert property_['field_template'] == 'storage_only' | |
280 type_name = '{}<{}>'.format(property_['pointer_type_name'], type_name) | |
281 | |
275 return Field( | 282 return Field( |
276 'property', | 283 'property', |
277 name_for_methods, | 284 name_for_methods, |
278 property_name=property_['name'], | 285 property_name=property_['name'], |
279 inherited=property_['inherited'], | 286 inherited=property_['inherited'], |
280 independent=property_['independent'], | 287 independent=property_['independent'], |
281 type_name=type_name, | 288 type_name=type_name, |
289 pointer_type_name=property_['pointer_type_name'], | |
282 field_template=property_['field_template'], | 290 field_template=property_['field_template'], |
283 field_group=property_['field_group'], | 291 field_group=property_['field_group'], |
284 size=size, | 292 size=size, |
285 default_value=default_value, | 293 default_value=default_value, |
286 has_custom_compare_and_copy=property_['has_custom_compare_and_copy'], | 294 has_custom_compare_and_copy=property_['has_custom_compare_and_copy'], |
287 getter_method_name=property_['getter'], | 295 getter_method_name=property_['getter'], |
288 setter_method_name=property_['setter'], | 296 setter_method_name=property_['setter'], |
289 initial_method_name=property_['initial'], | 297 initial_method_name=property_['initial'], |
290 ) | 298 ) |
291 | 299 |
292 | 300 |
293 def _create_inherited_flag_field(property_): | 301 def _create_inherited_flag_field(property_): |
294 """ | 302 """ |
295 Create the field used for an inheritance fast path from an independent CSS p roperty, | 303 Create the field used for an inheritance fast path from an independent CSS p roperty, |
296 and return the Field object. | 304 and return the Field object. |
297 """ | 305 """ |
298 name_for_methods = join_name(property_['name_for_methods'], 'is inherited') | 306 name_for_methods = join_name(property_['name_for_methods'], 'is inherited') |
299 return Field( | 307 return Field( |
300 'inherited_flag', | 308 'inherited_flag', |
301 name_for_methods, | 309 name_for_methods, |
302 property_name=property_['name'], | 310 property_name=property_['name'], |
303 type_name='bool', | 311 type_name='bool', |
312 pointer_type_name=None, | |
304 field_template='primitive', | 313 field_template='primitive', |
305 field_group=property_['field_group'], | 314 field_group=property_['field_group'], |
306 size=1, | 315 size=1, |
307 default_value='true', | 316 default_value='true', |
308 has_custom_compare_and_copy=False, | 317 has_custom_compare_and_copy=False, |
309 getter_method_name=method_name(name_for_methods), | 318 getter_method_name=method_name(name_for_methods), |
310 setter_method_name=method_name(join_name('set', name_for_methods)), | 319 setter_method_name=method_name(join_name('set', name_for_methods)), |
311 initial_method_name=method_name(join_name('initial', name_for_methods)), | 320 initial_method_name=method_name(join_name('initial', name_for_methods)), |
312 ) | 321 ) |
313 | 322 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
356 if not added_to_bucket: | 365 if not added_to_bucket: |
357 field_buckets.append([field]) | 366 field_buckets.append([field]) |
358 | 367 |
359 return _flatten_list(field_buckets) | 368 return _flatten_list(field_buckets) |
360 | 369 |
361 | 370 |
362 def _reorder_non_bit_fields(non_bit_fields): | 371 def _reorder_non_bit_fields(non_bit_fields): |
363 # A general rule of thumb is to sort members by their alignment requirement | 372 # A general rule of thumb is to sort members by their alignment requirement |
364 # (from biggest aligned to smallest). | 373 # (from biggest aligned to smallest). |
365 for field in non_bit_fields: | 374 for field in non_bit_fields: |
366 assert field.type_name in ALIGNMENT_ORDER, \ | 375 assert field.alignment_type in ALIGNMENT_ORDER, \ |
367 "Type {} has unknown alignment. Please update ALIGNMENT_ORDER to inc lude it.".format(field.type_name) | 376 "Type {} has unknown alignment. Please update ALIGNMENT_ORDER to inc lude it.".format(field.alignment_type) |
368 return list(sorted(non_bit_fields, key=lambda f: ALIGNMENT_ORDER.index(f.typ e_name))) | 377 return list(sorted(non_bit_fields, key=lambda f: ALIGNMENT_ORDER.index(f.ali gnment_type))) |
369 | 378 |
370 | 379 |
371 def _reorder_fields(fields): | 380 def _reorder_fields(fields): |
372 """ | 381 """ |
373 Returns a list of fields ordered to minimise padding. | 382 Returns a list of fields ordered to minimise padding. |
374 """ | 383 """ |
375 # Separate out bit fields from non bit fields | 384 # Separate out bit fields from non bit fields |
376 bit_fields = [field for field in fields if field.is_bit_field] | 385 bit_fields = [field for field in fields if field.is_bit_field] |
377 non_bit_fields = [field for field in fields if not field.is_bit_field] | 386 non_bit_fields = [field for field in fields if not field.is_bit_field] |
378 | 387 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
442 | 451 |
443 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') | 452 @template_expander.use_jinja('ComputedStyleBaseConstants.h.tmpl') |
444 def generate_base_computed_style_constants(self): | 453 def generate_base_computed_style_constants(self): |
445 return { | 454 return { |
446 'properties': self._properties, | 455 'properties': self._properties, |
447 'enums': self._generated_enums, | 456 'enums': self._generated_enums, |
448 } | 457 } |
449 | 458 |
450 if __name__ == '__main__': | 459 if __name__ == '__main__': |
451 json5_generator.Maker(ComputedStyleBaseWriter).main() | 460 json5_generator.Maker(ComputedStyleBaseWriter).main() |
OLD | NEW |