{
    Let G. make
}

Where

Let make MAP.
    Let compare. MAP.compare
    In
    Let ADJ.
        {
            Let vertex item. item.0
            Let neighbors item. item.1
        }
    Let SET. (SEARCH.SET compare)
    In
    Let min a b. If (a < b) a b
    In
    Define traverse g adj i stack preorder assigned components.
        Let v. (ADJ.vertex adj)
        Let neighbors. (ADJ.neighbors adj)
        In
        Let preorder. (MAP.insert preorder {v i})
        Let stack. (v::stack)
        In
        Let {link i' stack preorder assigned components}.
            (LIST.reduce neighbors
                {i (i + 1) stack preorder assigned components}
                Func state w.
                    Let {link i stack preorder assigned components}. state
                    In
                    Match (SET.search assigned w)
                    | `just._ state
                    | `nothing
                        Match (MAP.search preorder w)
                        | `just.{_ j}
                            Let link. (min link j)
                            In
                            {link i stack preorder assigned components}
                        | `nothing
                            Let adj.
                                Match (MAP.search g w)
                                | `nothing {w []}
                                | `just.adj adj
                                ;
                            In
                            Let {link' i stack preorder assigned components}.
                                (traverse g adj i stack preorder assigned
                                    components)
                            In
                            Let link. (min link link')
                            In
                            {link i stack preorder assigned components}
                        ;
                    ;)
        In
        If (i = link)
            Block
                Let {c stack assigned}.
                    Begin (gathering [] stack assigned)
                        Define gathering c stack assigned.
                            Match stack
                            | `cons.{w stack}
                                Let assigned. (SET.insert assigned w)
                                In
                                Match (compare w v)
                                | `equal {(v::c) stack assigned}
                                | _ Goto (gathering (w::c) stack assigned)
                                ;
                            ;
                In
                {link i' stack preorder assigned (c::components)}
            {link i' stack preorder assigned components}
    In
    Define traversing g adjs i stack preorder assigned components.
        Match adjs
        | `nil (LIST.reverse components)
        | `cons.{adj adjs}
            Match (SET.search assigned (ADJ.vertex adj))
            | `just._
                Goto (traversing g adjs i stack preorder assigned components)
            | `nothing
                Let {link i stack preorder assigned components}.
                    (traverse g adj i stack preorder assigned components)
                In
                Goto (traversing g adjs i stack preorder assigned components)
            ;
        ;
    In
    {
        Let strongly_connected_components g.
            (traversing g (MAP.list g) 0 [] MAP.empty SET.empty [])
    }

Where

Let die. OS.die

Where

Let LIST. Package "list"
Let OS. Package "os"
Let SEARCH. Package "search"
Let STDIO. Package "stdio"