PreviousUpNext

15.4.57  src/app/makelib/depend/find-reachable-sml-nodes.pkg

## find-reachable-sml-nodes.pkg
## (C) 1999 Lucent Technologies, Bell Laboratories
## Author: Matthias Blume (blume@kurims.kyoto-u.ac.jp)

# Compiled by:
#     src/app/makelib/makelib.sublib



# Get the set of reachable SML_NODEs in a given dependency graph.



###                "Ah, but a man's grasp should exceed his reach,
###                 Or what's a heaven for?"
###
###                                    -- Robert Browning



stipulate
    package flt =  frozenlib_tome;                                              # frozenlib_tome                        is from   src/app/makelib/freezefile/frozenlib-tome.pkg
    package fts =  frozenlib_tome_set;                                          # frozenlib_tome_set                    is from   src/app/makelib/freezefile/frozenlib-tome-set.pkg
    package lg  =  inter_library_dependency_graph;                              # inter_library_dependency_graph        is from   src/app/makelib/depend/inter-library-dependency-graph.pkg
    package sg  =  intra_library_dependency_graph;                              # intra_library_dependency_graph        is from   src/app/makelib/depend/intra-library-dependency-graph.pkg
    package spm =  source_path_map;                                             # source_path_map                       is from   src/app/makelib/paths/source-path-map.pkg
    package sps =  source_path_set;                                             # source_path_set                       is from   src/app/makelib/paths/source-path-set.pkg
    package sym =  symbol_map;                                                  # symbol_map                            is from   src/app/makelib/stuff/symbol-map.pkg
    package tts =  thawedlib_tome_set;                                          # thawedlib_tome_set                    is from   src/app/makelib/compilable/thawedlib-tome-set.pkg
herein

    api Find_Reachable_Sml_Nodes {
        #
        #

        # These two functions simply give you the set of (non-frozen)
        # .compileds reachable from some root and the fringe of frozen
        # .compileds that surrounds the non-frozen portion.
        #
        reachable'
            :
            List( sg::Tome_Tin )
            ->
            ( tts::Set,
              fts::Set
            );

        reachable
            :
            lg::Inter_Library_Dependency_Graph
            ->
            ( tts::Set,
              fts::Set
            );



        # "make_thawedlib_tome_tin_map" gives us handles at arbitrary points within
        # the (non-frozen) portion of a dependency graph.
        # This is used by "server" mode compiler.
        #
        make__sourcepath__to__thawedlib_tome_tin__map
            :
            lg::Inter_Library_Dependency_Graph
            ->
            spm::Map( sg::Thawedlib_Tome_Tin );



        # Given a library g, "groupsOf g" gets the set of
        # sublibraries (but not sub-freezefiles) of that library.
        # The result will include the argument itself:
        #
        groups_of:  lg::Inter_Library_Dependency_Graph
                     ->
                     sps::Set;



        # Given an arbitrary library graph rooted at library g, "freezefiles_of g"
        # gets the set of stable libraries reachable from g.
        #
        freezefiles_of:  lg::Inter_Library_Dependency_Graph
                          ->
                          spm::Map( lg::Inter_Library_Dependency_Graph );



        # Given a "closed" subset of (non-stable) nodes in a dependency graph,
        # "frontier" gives you the set of frontier nodes of that set.  The
        # closed set is given by its indicator function (first argument).
        # ("closed" means that if a node's ancestors are all in
        # the set, then so is the node itself.  A frontier node is a node that
        # is in the set but either not all of its ancestors are or the node
        # is an export node.)

        frontier:  (flt::Frozenlib_Tome -> Bool)
                   ->
                   lg::Inter_Library_Dependency_Graph
                   ->
                   fts::Set;
    };
end;



stipulate
    package fts =  frozenlib_tome_set;                                          # frozenlib_tome_set                    is from   src/app/makelib/freezefile/frozenlib-tome-set.pkg
    package lg  =  inter_library_dependency_graph;                              # inter_library_dependency_graph        is from   src/app/makelib/depend/inter-library-dependency-graph.pkg
    package sg  =  intra_library_dependency_graph;                              # intra_library_dependency_graph        is from   src/app/makelib/depend/intra-library-dependency-graph.pkg
    package spm =  source_path_map;                                             # source_path_map                       is from   src/app/makelib/paths/source-path-map.pkg
    package sps =  source_path_set;                                             # source_path_set                       is from   src/app/makelib/paths/source-path-set.pkg
    package sym =  symbol_map;                                                  # symbol_map                            is from   src/app/makelib/stuff/symbol-map.pkg
    package tlt =  thawedlib_tome;                                              # thawedlib_tome                        is from   src/app/makelib/compilable/thawedlib-tome.pkg
    package tts =  thawedlib_tome_set;                                          # thawedlib_tome_set                    is from   src/app/makelib/compilable/thawedlib-tome-set.pkg
herein


    package   find_reachable_sml_nodes
    :         Find_Reachable_Sml_Nodes                                          # Find_Reachable_Sml_Nodes              is from   src/app/makelib/depend/find-reachable-sml-nodes.pkg
    {
        stipulate
            #
            fun reach
                    #
                    { add, member, empty }
                    #
                    (tome_tins:   List( sg::Tome_Tin ))
                =
                {   fun thawedlib_tomenode
                          #
                          ( node as sg::THAWEDLIB_TOME_TIN { thawedlib_tome, near_imports, far_imports },
                            #   
                            (known, stabfringe)
                          )
                        =
                        if (member (known, thawedlib_tome))
                            #                   
                            (known, stabfringe);
                        else
                            fold_forward
                                #
                                do_masked_tome
                                #
                                (   fold_forward
                                        thawedlib_tomenode
                                        (add (known, thawedlib_tome, node), stabfringe)
                                        near_imports
                                )
                                #
                                far_imports;
                        fi

                    also
                    fun do_masked_tome
                          (
                            { tome_tin, ... }: sg::Masked_Tome,                 # Value being folded.
                            known_and_fringe                                    # Fold-result accumulators.
                          )
                        =
                        do_tome_tin (tome_tin, known_and_fringe)


                    also
                    fun do_tome_tin (sg::TOME_IN_FROZENLIB { frozenlib_tome_tin => sg::FROZENLIB_TOME_TIN tin, ... }, (known, stabfringe))
                            =>
                            (known, fts::add (stabfringe, tin.frozenlib_tome));

                        do_tome_tin (sg::TOME_IN_THAWEDLIB node, known_and_fringe)
                            =>
                            thawedlib_tomenode (node, known_and_fringe);
                    end;

                    fold_forward
                        do_tome_tin
                        (empty,  fts::empty)
                        tome_tins;

                };

            fun force f
                =
                f ();

            fun fat_tome_map' (exports: sym::Map( lg::Fat_Tome ), acc)
                =
                {   fun add (m, tome, x) =   spm::set          (m, tlt::sourcepath_of tome, x);
                    fun member (m, tome) =   spm::contains_key (m, tlt::sourcepath_of tome);

                    #1 (reach { add, member, empty => acc }
                              (map (.tome_tin o force o .masked_tome_thunk)
                                   (sym::vals_list exports)));
                };
        herein
            reachable'
                =
                reach { add    =>  \\ (s, i, _) =  tts::add (s, i),
                        member =>  tts::member,
                        empty  =>  tts::empty
                      };

            fun reachable (lg::LIBRARY { catalog, ... } )
                    =>
                    reachable'
                        (map (.tome_tin o force o .masked_tome_thunk)
                             (sym::vals_list  catalog)
                        );

                reachable lg::BAD_LIBRARY
                    =>
                    ( tts::empty,
                      fts::empty
                    );
            end;

            fun make__sourcepath__to__thawedlib_tome_tin__map  lib
                =
                #1 (do_library (lib, (spm::empty, sps::empty)))
                where
                    fun do_library (lib as lg::LIBRARY library, (a, seen))
                            =>
                            {   library ->  { catalog, sublibraries, libfile, ... };

                                if (sps::member (seen, libfile))
                                    #                           
                                    (a, seen);
                                else
                                    fold_forward
                                        (\\ (lt: lg::Library_Thunk, x) =   do_library (lt.library_thunk (), x))
                                        (fat_tome_map' (catalog, a), sps::add (seen, libfile))
                                        sublibraries;
                                fi;
                            };

                        do_library (lg::BAD_LIBRARY, x)
                            =>
                            x;
                    end;
                end;


            fun groups_of lib
                =
                {   fun sublibraries (lg::LIBRARY { more => lg::SUBLIBRARY x, ... } )
                            =>
                            x.sublibraries;

                        sublibraries (lg::LIBRARY { more => lg::MAIN_LIBRARY { frozen_vs_thawed_stuff => lg::THAWEDLIB_STUFF x, ... }, ... } )
                            =>
                            x.sublibraries;

                        sublibraries _ => [];
                    end;


                    fun go (lib as lg::LIBRARY { libfile, ... }, a)
                            =>
                            {   sgl =  sublibraries lib;

                                fun sl (lt: lg::Library_Thunk, a)
                                    =
                                    case (lt.library_thunk ())
                                        #                                 
                                        lib as lg::LIBRARY { more => lg::SUBLIBRARY _, ... }
                                            =>
                                            if (sps::member (a, lt.libfile))
                                                a;
                                            else
                                                go (lib, a);
                                            fi;
                                        #
                                        _   =>   a;
                                    esac;

                                sps::add (fold_forward sl a sgl, libfile);
                            };

                        go (lg::BAD_LIBRARY, a)
                            =>
                            a;
                    end;

                    go (lib, sps::empty);
                };


            fun freezefiles_of (lib as lg::LIBRARY { libfile, ... } )
                    =>
                    {   fun slo' ((p, lib as lg::LIBRARY library), (seen, result))
                                =>
                                {   library ->  { more, sublibraries, ... };

                                    if (sps::member (seen, p))
                                        #                                   
                                        (seen, result);
                                    else
                                        my (seen, result)
                                            =
                                            fold_forward
                                                slo
                                                (seen, result)
                                                sublibraries;

                                        seen = sps::add (seen, p);

                                        case more
                                            #
                                            lg::MAIN_LIBRARY { frozen_vs_thawed_stuff => lg::FROZENLIB_STUFF _, ... }
                                                =>
                                                ( seen,
                                                  spm::set (result, p, lib)
                                                );
                                            #
                                            _   =>   (seen, result);
                                        esac;
                                    fi;
                                };

                            slo' ((_, lg::BAD_LIBRARY), x)
                                =>
                                x;
                        end 

                        also
                        fun slo  (lt: lg::Library_Thunk,  x)
                            =
                            slo' ((lt.libfile, lt.library_thunk ()), x);


                        #2 (slo' ( (libfile, lib),
                                   ( sps::empty,
                                     spm::empty
                                   )
                                 )
                           );
                    };


                freezefiles_of lg::BAD_LIBRARY
                    =>
                    spm::empty;
            end;


            fun frontier in_set (lg::LIBRARY { catalog, ... } )
                    =>
                    {   fun bnode (sg::FROZENLIB_TOME_TIN tin, (frozen_compilables_seen, f))
                            =
                            {   tin -> { frozenlib_tome, near_imports, ... };

                                if (fts::member (frozen_compilables_seen, frozenlib_tome))
                                    #
                                    (frozen_compilables_seen, f);
                                else
                                    frozen_compilables_seen =  fts::add (frozen_compilables_seen, frozenlib_tome);

                                    if (in_set frozenlib_tome)
                                        #
                                        (frozen_compilables_seen, fts::add (f, frozenlib_tome));
                                    else 
                                        fold_forward bnode (frozen_compilables_seen, f) near_imports;
                                    fi;
                                fi;
                            };


                        fun get_bn
                              ( t:         lg::Fat_Tome,
                                results:   List( sg::Frozenlib_Tome_Tin )
                              )
                            =
                            case (t.masked_tome_thunk ())
                                #                         
                                { tome_tin => sg::TOME_IN_FROZENLIB r, ... }
                                    =>
                                    r.frozenlib_tome_tin ! results;

                                _   =>
                                    results;
                            esac;


                        bnl =
                           sym::fold_forward
                               get_bn
                               []
                               catalog;

                        #2 (fold_forward
                               bnode
                               (fts::empty, fts::empty)
                               bnl
                           );
                    };

                frontier _ lg::BAD_LIBRARY
                    =>
                    fts::empty;
            end;
        end;
    };
end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext