'Tarjan\'s strongly connected components algorithm.
See also:
- http://en.wikipedia.org/wiki/Tarjan\'s_strongly_connected_components_algorithm'

def _tarjan(self, function, order, stack, orders, lowlinks, visited):

    visited.add(function)
    orders[function] = order
    lowlinks[function] = order
    order += 1
    pos = len(stack)
    stack.append(function)
    for call in function.calls.itervalues():
        callee = self.functions[call.callee_id]
        if (callee not in orders):
            order = self._tarjan(callee, order, stack, orders, lowlinks, visited)
            lowlinks[function] = min(lowlinks[function], lowlinks[callee])
        elif (callee in stack):
            lowlinks[function] = min(lowlinks[function], orders[callee])
    if (lowlinks[function] == orders[function]):
        members = stack[pos:]
        del stack[pos:]
        if (len(members) > 1):
            cycle = Cycle()
            for member in members:
                cycle.add_function(member)
    return order
