nodes: 0, module; 1, function_definition; 2, function_name:_topological_sort; 3, parameters; 4, block; 5, identifier:self; 6, expression_statement; 7, expression_statement; 8, expression_statement; 9, expression_statement; 10, function_definition; 11, comment:# node is initially weighted with the number of immediate dependencies; 12, for_statement; 13, comment:# Start with a list of nodes who have no dependents; 14, expression_statement; 15, while_statement; 16, expression_statement; 17, expression_statement; 18, comment:"""
          Kahn's algorithm for Topological Sorting
          - Finds cycles in graph
          - Computes dependency weight
          """; 19, assignment; 20, assignment; 21, assignment; 22, function_name:get_pointers_for_edge_nodes; 23, parameters; 24, block; 25, identifier:node; 26, identifier:nodes; 27, block; 28, assignment; 29, identifier:resolved; 30, block; 31, assignment; 32, assignment; 33, identifier:sorted_graph; 34, list; 35, identifier:node_map; 36, call; 37, identifier:nodes; 38, list_comprehension; 39, identifier:visitor_decorated_node; 40, expression_statement; 41, expression_statement; 42, for_statement; 43, return_statement; 44, for_statement; 45, identifier:resolved; 46, list_comprehension; 47, expression_statement; 48, expression_statement; 49, for_statement; 50, attribute; 51, list_comprehension; 52, attribute; 53, call; 54, attribute; 55, argument_list; 56, call; 57, for_in_clause; 58, assignment; 59, assignment; 60, identifier:node; 61, identifier:nodes; 62, block; 63, identifier:edges; 64, identifier:edge; 65, call; 66, block; 67, identifier:node; 68, for_in_clause; 69, if_clause; 70, assignment; 71, call; 72, identifier:edge; 73, call; 74, block; 75, identifier:self; 76, identifier:_circular_dependencies; 77, call; 78, for_in_clause; 79, if_clause; 80, identifier:self; 81, identifier:_sorted_nodes; 82, identifier:list; 83, argument_list; 84, attribute; 85, identifier:get_nodes; 86, identifier:NodeVisitor; 87, argument_list; 88, identifier:node; 89, identifier:node_map; 90, identifier:edges; 91, list; 92, identifier:edge_ids; 93, call; 94, if_statement; 95, identifier:get_pointers_for_edge_nodes; 96, argument_list; 97, expression_statement; 98, identifier:node; 99, identifier:nodes; 100, comparison_operator:node.get_weight() == 0; 101, identifier:node; 102, call; 103, attribute; 104, argument_list; 105, identifier:get_pointers_for_edge_nodes; 106, argument_list; 107, expression_statement; 108, if_statement; 109, attribute; 110, argument_list; 111, identifier:node; 112, identifier:nodes; 113, comparison_operator:node.get_weight() > 0; 114, call; 115, identifier:self; 116, identifier:_graph; 117, subscript; 118, attribute; 119, argument_list; 120, comparison_operator:node.get_id() in edge_ids; 121, block; 122, identifier:node; 123, call; 124, call; 125, integer:0; 126, attribute; 127, argument_list; 128, identifier:sorted_graph; 129, identifier:append; 130, identifier:node; 131, identifier:node; 132, call; 133, comparison_operator:edge.get_weight() == 0; 134, block; 135, identifier:node; 136, identifier:get_node; 137, call; 138, integer:0; 139, identifier:reversed; 140, argument_list; 141, identifier:node_map; 142, identifier:node; 143, call; 144, identifier:get_edges; 145, call; 146, identifier:edge_ids; 147, expression_statement; 148, attribute; 149, argument_list; 150, attribute; 151, argument_list; 152, identifier:resolved; 153, identifier:pop; 154, attribute; 155, argument_list; 156, call; 157, integer:0; 158, expression_statement; 159, attribute; 160, argument_list; 161, list_comprehension; 162, attribute; 163, argument_list; 164, attribute; 165, argument_list; 166, call; 167, identifier:edge; 168, identifier:increment; 169, identifier:node; 170, identifier:get_weight; 171, identifier:edge; 172, identifier:decrement; 173, attribute; 174, argument_list; 175, call; 176, identifier:node; 177, identifier:get_weight; 178, call; 179, for_in_clause; 180, identifier:visitor_decorated_node; 181, identifier:get_node; 182, identifier:node; 183, identifier:get_id; 184, attribute; 185, argument_list; 186, identifier:edge; 187, identifier:get_weight; 188, attribute; 189, argument_list; 190, attribute; 191, argument_list; 192, identifier:node; 193, identifier:sorted_graph; 194, identifier:edges; 195, identifier:append; 196, identifier:node; 197, identifier:resolved; 198, identifier:append; 199, identifier:edge; 200, identifier:node; 201, identifier:get_node
code: def _topological_sort(self):
          """
          Kahn's algorithm for Topological Sorting
          - Finds cycles in graph
          - Computes dependency weight
          """
          sorted_graph = []
          node_map = self._graph.get_nodes()
  
          nodes = [NodeVisitor(node_map[node]) for node in node_map]
  
          def get_pointers_for_edge_nodes(visitor_decorated_node):
              edges = []
              edge_ids = visitor_decorated_node.get_node().get_edges()
              for node in nodes:
                  if node.get_id() in edge_ids:
                      edges.append(node)
  
              return edges
  
          # node is initially weighted with the number of immediate dependencies
          for node in nodes:
              for edge in get_pointers_for_edge_nodes(node):
                  edge.increment()
  
          # Start with a list of nodes who have no dependents
          resolved = [node for node in nodes if node.get_weight() == 0]
  
          while resolved:
              node = resolved.pop()
              sorted_graph.append(node)
  
              for edge in get_pointers_for_edge_nodes(node):
                  edge.decrement()
                  if edge.get_weight() == 0:
                      resolved.append(edge)
  
          self._circular_dependencies = [
              node.get_node() for node in nodes if node.get_weight() > 0]
  
          self._sorted_nodes = list(reversed(
              [node.get_node() for node in sorted_graph]))