OLD | NEW |
---|---|
1 # Copyright (c) 2012 Google Inc. All rights reserved. | 1 # Copyright (c) 2012 Google Inc. 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 from compiler.ast import Const | 5 from compiler.ast import Const |
6 from compiler.ast import Dict | 6 from compiler.ast import Dict |
7 from compiler.ast import Discard | 7 from compiler.ast import Discard |
8 from compiler.ast import List | 8 from compiler.ast import List |
9 from compiler.ast import Module | 9 from compiler.ast import Module |
10 from compiler.ast import Node | 10 from compiler.ast import Node |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
51 'outputs', | 51 'outputs', |
52 'sources', | 52 'sources', |
53 ] | 53 ] |
54 path_sections = set() | 54 path_sections = set() |
55 | 55 |
56 # These per-process dictionaries are used to cache build file data when loading | 56 # These per-process dictionaries are used to cache build file data when loading |
57 # in parallel mode. | 57 # in parallel mode. |
58 per_process_data = {} | 58 per_process_data = {} |
59 per_process_aux_data = {} | 59 per_process_aux_data = {} |
60 | 60 |
61 def OrderDeterministically(l, **kwargs): | |
62 """ Sorts l so that it is ordered deterministically. """ | |
63 return sorted(l, **kwargs) | |
mithro-old
2015/12/10 03:15:28
DRY
Zachary Forman
2015/12/30 02:18:43
Done.
| |
64 | |
61 def IsPathSection(section): | 65 def IsPathSection(section): |
62 # If section ends in one of the '=+?!' characters, it's applied to a section | 66 # If section ends in one of the '=+?!' characters, it's applied to a section |
63 # without the trailing characters. '/' is notably absent from this list, | 67 # without the trailing characters. '/' is notably absent from this list, |
64 # because there's no way for a regular expression to be treated as a path. | 68 # because there's no way for a regular expression to be treated as a path. |
65 while section and section[-1:] in '=+?!': | 69 while section and section[-1:] in '=+?!': |
66 section = section[:-1] | 70 section = section[:-1] |
67 | 71 |
68 if section in path_sections: | 72 if section in path_sections: |
69 return True | 73 return True |
70 | 74 |
(...skipping 1461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1532 def __repr__(self): | 1536 def __repr__(self): |
1533 return '<DependencyGraphNode: %r>' % self.ref | 1537 return '<DependencyGraphNode: %r>' % self.ref |
1534 | 1538 |
1535 def FlattenToList(self): | 1539 def FlattenToList(self): |
1536 # flat_list is the sorted list of dependencies - actually, the list items | 1540 # flat_list is the sorted list of dependencies - actually, the list items |
1537 # are the "ref" attributes of DependencyGraphNodes. Every target will | 1541 # are the "ref" attributes of DependencyGraphNodes. Every target will |
1538 # appear in flat_list after all of its dependencies, and before all of its | 1542 # appear in flat_list after all of its dependencies, and before all of its |
1539 # dependents. | 1543 # dependents. |
1540 flat_list = OrderedSet() | 1544 flat_list = OrderedSet() |
1541 | 1545 |
1546 def ExtractNodeRef(node): | |
1547 """Extracts the object that the node represents from the given node.""" | |
1548 return node.ref | |
1549 | |
1542 # in_degree_zeros is the list of DependencyGraphNodes that have no | 1550 # in_degree_zeros is the list of DependencyGraphNodes that have no |
1543 # dependencies not in flat_list. Initially, it is a copy of the children | 1551 # dependencies not in flat_list. Initially, it is a copy of the children |
1544 # of this node, because when the graph was built, nodes with no | 1552 # of this node, because when the graph was built, nodes with no |
1545 # dependencies were made implicit dependents of the root node. | 1553 # dependencies were made implicit dependents of the root node. |
1546 in_degree_zeros = set(self.dependents[:]) | 1554 in_degree_zeros = OrderDeterministically(self.dependents[:], |
1555 key=ExtractNodeRef) | |
1547 | 1556 |
1548 while in_degree_zeros: | 1557 while in_degree_zeros: |
1549 # Nodes in in_degree_zeros have no dependencies not in flat_list, so they | 1558 # Nodes in in_degree_zeros have no dependencies not in flat_list, so they |
1550 # can be appended to flat_list. Take these nodes out of in_degree_zeros | 1559 # can be appended to flat_list. Take these nodes out of in_degree_zeros |
1551 # as work progresses, so that the next node to process from the list can | 1560 # as work progresses, so that the next node to process from the list can |
1552 # always be accessed at a consistent position. | 1561 # always be accessed at a consistent position. |
1553 node = in_degree_zeros.pop() | 1562 node = in_degree_zeros.pop() |
1554 flat_list.add(node.ref) | 1563 flat_list.add(node.ref) |
1555 | 1564 |
1556 # Look at dependents of the node just added to flat_list. Some of them | 1565 # Look at dependents of the node just added to flat_list. Some of them |
1557 # may now belong in in_degree_zeros. | 1566 # may now belong in in_degree_zeros. |
1558 for node_dependent in node.dependents: | 1567 for node_dependent in OrderDeterministically(node.dependents, |
1568 key=ExtractNodeRef): | |
1559 is_in_degree_zero = True | 1569 is_in_degree_zero = True |
1560 # TODO: We want to check through the | 1570 # TODO: We want to check through the |
1561 # node_dependent.dependencies list but if it's long and we | 1571 # node_dependent.dependencies list but if it's long and we |
1562 # always start at the beginning, then we get O(n^2) behaviour. | 1572 # always start at the beginning, then we get O(n^2) behaviour. |
1563 for node_dependent_dependency in node_dependent.dependencies: | 1573 for node_dependent_dependency in ( |
1574 OrderDeterministically(node_dependent.dependencies, | |
1575 key=ExtractNodeRef)): | |
1564 if not node_dependent_dependency.ref in flat_list: | 1576 if not node_dependent_dependency.ref in flat_list: |
1565 # The dependent one or more dependencies not in flat_list. There | 1577 # The dependent one or more dependencies not in flat_list. There |
1566 # will be more chances to add it to flat_list when examining | 1578 # will be more chances to add it to flat_list when examining |
1567 # it again as a dependent of those other dependencies, provided | 1579 # it again as a dependent of those other dependencies, provided |
1568 # that there are no cycles. | 1580 # that there are no cycles. |
1569 is_in_degree_zero = False | 1581 is_in_degree_zero = False |
1570 break | 1582 break |
1571 | 1583 |
1572 if is_in_degree_zero: | 1584 if is_in_degree_zero: |
1573 # All of the dependent's dependencies are already in flat_list. Add | 1585 # All of the dependent's dependencies are already in flat_list. Add |
1574 # it to in_degree_zeros where it will be processed in a future | 1586 # it to in_degree_zeros where it will be processed in a future |
1575 # iteration of the outer loop. | 1587 # iteration of the outer loop. |
1576 in_degree_zeros.add(node_dependent) | 1588 in_degree_zeros += [node_dependent] |
1577 | 1589 |
1578 return list(flat_list) | 1590 return list(flat_list) |
1579 | 1591 |
1580 def FindCycles(self): | 1592 def FindCycles(self): |
1581 """ | 1593 """ |
1582 Returns a list of cycles in the graph, where each cycle is its own list. | 1594 Returns a list of cycles in the graph, where each cycle is its own list. |
1583 """ | 1595 """ |
1584 results = [] | 1596 results = [] |
1585 visited = set() | 1597 visited = set() |
1586 | 1598 |
(...skipping 1298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2885 ValidateRunAsInTarget(target, target_dict, build_file) | 2897 ValidateRunAsInTarget(target, target_dict, build_file) |
2886 ValidateActionsInTarget(target, target_dict, build_file) | 2898 ValidateActionsInTarget(target, target_dict, build_file) |
2887 | 2899 |
2888 # Generators might not expect ints. Turn them into strs. | 2900 # Generators might not expect ints. Turn them into strs. |
2889 TurnIntIntoStrInDict(data) | 2901 TurnIntIntoStrInDict(data) |
2890 | 2902 |
2891 # TODO(mark): Return |data| for now because the generator needs a list of | 2903 # TODO(mark): Return |data| for now because the generator needs a list of |
2892 # build files that came in. In the future, maybe it should just accept | 2904 # build files that came in. In the future, maybe it should just accept |
2893 # a list, and not the whole data dict. | 2905 # a list, and not the whole data dict. |
2894 return [flat_list, targets, data] | 2906 return [flat_list, targets, data] |
OLD | NEW |