nodes: 0, module; 1, function_definition; 2, function_name:_sort_handlers; 3, parameters; 4, block; 5, identifier:cls; 6, identifier:signals; 7, identifier:handlers; 8, identifier:configs; 9, expression_statement; 10, function_definition; 11, expression_statement; 12, expression_statement; 13, for_statement; 14, for_statement; 15, return_statement; 16, comment:"""Sort class defined handlers to give precedence to those declared at
          lower level. ``config`` can contain two keys ``begin`` or ``end`` that
          will further reposition the handler at the two extremes.
          """; 17, function_name:macro_precedence_sorter; 18, parameters; 19, block; 20, assignment; 21, assignment; 22, pattern_list; 23, call; 24, block; 25, pattern_list; 26, call; 27, block; 28, identifier:per_signal; 29, identifier:flags; 30, identifier:hname; 31, expression_statement; 32, expression_statement; 33, expression_statement; 34, if_statement; 35, if_statement; 36, identifier:levels_count; 37, call; 38, identifier:per_signal; 39, call; 40, identifier:level; 41, identifier:m; 42, identifier:enumerate; 43, argument_list; 44, for_statement; 45, identifier:sig_name; 46, identifier:sig_handlers; 47, attribute; 48, argument_list; 49, if_statement; 50, comment:"""The default is to sort 'bottom_up', with lower level getting
              executed first, but sometimes you need them reversed."""; 51, assignment; 52, assignment; 53, identifier:topdown_sort; 54, block; 55, else_clause; 56, comparison_operator:'begin' in data; 57, block; 58, elif_clause; 59, else_clause; 60, identifier:len; 61, argument_list; 62, identifier:defaultdict; 63, argument_list; 64, call; 65, pattern_list; 66, call; 67, block; 68, identifier:per_signal; 69, identifier:items; 70, comparison_operator:sig_name in signals; 71, comment:# it may be on a mixin; 72, block; 73, identifier:data; 74, subscript; 75, identifier:topdown_sort; 76, comparison_operator:SignalOptions.SORT_TOPDOWN in flags; 77, expression_statement; 78, block; 79, string; 80, identifier:data; 81, return_statement; 82, comparison_operator:'end' in data; 83, block; 84, block; 85, attribute; 86, identifier:list; 87, identifier:reversed; 88, argument_list; 89, identifier:hname; 90, identifier:sig_name; 91, attribute; 92, argument_list; 93, expression_statement; 94, if_statement; 95, identifier:sig_name; 96, identifier:signals; 97, expression_statement; 98, expression_statement; 99, identifier:configs; 100, identifier:hname; 101, attribute; 102, identifier:flags; 103, assignment; 104, expression_statement; 105, string_content:begin; 106, tuple; 107, string; 108, identifier:data; 109, return_statement; 110, return_statement; 111, identifier:handlers; 112, identifier:maps; 113, attribute; 114, identifier:m; 115, identifier:items; 116, assignment; 117, comparison_operator:hname not in sig_handlers; 118, block; 119, assignment; 120, call; 121, identifier:SignalOptions; 122, identifier:SORT_TOPDOWN; 123, identifier:level; 124, binary_operator:levels_count - 1 - data['level']; 125, assignment; 126, unary_operator; 127, identifier:level; 128, identifier:hname; 129, string_content:end; 130, tuple; 131, tuple; 132, identifier:handlers; 133, identifier:maps; 134, identifier:sig_handlers; 135, subscript; 136, identifier:hname; 137, identifier:sig_handlers; 138, expression_statement; 139, expression_statement; 140, identifier:flags; 141, attribute; 142, attribute; 143, argument_list; 144, binary_operator:levels_count - 1; 145, subscript; 146, identifier:level; 147, subscript; 148, integer:1; 149, integer:1; 150, identifier:level; 151, identifier:hname; 152, integer:0; 153, identifier:level; 154, identifier:hname; 155, identifier:per_signal; 156, identifier:sig_name; 157, assignment; 158, call; 159, subscript; 160, identifier:flags; 161, identifier:sig_handlers; 162, identifier:sort; 163, keyword_argument; 164, identifier:levels_count; 165, integer:1; 166, identifier:data; 167, string; 168, identifier:data; 169, string; 170, subscript; 171, identifier:level; 172, attribute; 173, argument_list; 174, identifier:signals; 175, identifier:sig_name; 176, identifier:key; 177, call; 178, string_content:level; 179, string_content:level; 180, subscript; 181, string; 182, identifier:sig_handlers; 183, identifier:append; 184, identifier:hname; 185, identifier:partial; 186, argument_list; 187, identifier:configs; 188, identifier:hname; 189, string_content:level; 190, identifier:macro_precedence_sorter; 191, identifier:flags
code: def _sort_handlers(cls, signals, handlers, configs):
          """Sort class defined handlers to give precedence to those declared at
          lower level. ``config`` can contain two keys ``begin`` or ``end`` that
          will further reposition the handler at the two extremes.
          """
          def macro_precedence_sorter(flags, hname):
              """The default is to sort 'bottom_up', with lower level getting
              executed first, but sometimes you need them reversed."""
              data = configs[hname]
              topdown_sort = SignalOptions.SORT_TOPDOWN in flags
              if topdown_sort:
                  level = levels_count - 1 - data['level']
              else:
                  level = data['level']
              if 'begin' in data:
                  return (-1, level, hname)
              elif 'end' in data:
                  return (1, level, hname)
              else:
                  return (0, level, hname)
  
          levels_count = len(handlers.maps)
          per_signal = defaultdict(list)
          for level, m in enumerate(reversed(handlers.maps)):
              for hname, sig_name in m.items():
                  sig_handlers = per_signal[sig_name]
                  if hname not in sig_handlers:
                      configs[hname]['level'] = level
                      sig_handlers.append(hname)
          for sig_name, sig_handlers in per_signal.items():
              if sig_name in signals:  # it may be on a mixin
                  flags = signals[sig_name].flags
                  sig_handlers.sort(key=partial(macro_precedence_sorter,
                                                flags))
          return per_signal