PreviousUpNext

15.4.63  src/app/makelib/depend/scan-dependency-graph.pkg

## scan-dependency-graph.pkg
## (C) 1999 Lucent Technologies, Bell Laboratories
## Author: Matthias Blume (blume@kurims.kyoto-u.ac.jp)

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



# Visit every node in a dependency graph,
# gathering caller-defined per-node information.
#
# At the moment, this is only called by
#    src/app/makelib/mythryl-compiler-compiler/find-set-of-compiledfiles-for-executable.pkg


stipulate
    package sg =  intra_library_dependency_graph;       # intra_library_dependency_graph        is from   src/app/makelib/depend/intra-library-dependency-graph.pkg
    package lg =  inter_library_dependency_graph;       # inter_library_dependency_graph        is from   src/app/makelib/depend/inter-library-dependency-graph.pkg
herein
    package scan_dependency_graph
    :
    api {
         scan_dependency_graph
                : {   a7file_info:       frozenlib_tome::Frozenlib_Tome -> A_element,
                      thawedlib_tome:   thawedlib_tome::Thawedlib_Tome  -> A_element,

                      cons:  (A_element, A_elements) -> A_elements,
                      nil:   A_elements
                  }
               -> lg::Inter_Library_Dependency_Graph
               -> A_elements;
    }
    {


        # See if we've already added a freezefile or sml file (Thawedlib_Tome)
        # to our (frozenlib_tome_set, Thawedlib_Tome) accumulator 'm' == (bs, ss):
        #
        fun freezefile_is_registered ((bs, ss), i)   =   frozenlib_tome_set::member (bs, i);
        fun sml_file_is_registered       ((bs, ss), i)   =   thawedlib_tome_set::member (ss, i);

        # Add a freezefile or sml file
        # (Thawedlib_Tome) to our accumulator 'm' == (bs, ss):


        fun register_stable_library   ((bs, ss), i)   =   (frozenlib_tome_set::add (bs, i), ss);
        fun register_source_file         ((bs, ss), i)   =   (bs, thawedlib_tome_set::add (ss, i));

        # Apply do_element to every element of given list, 
        # accumulating results in 'm' via do_element side-effects
        # and returning k (m) when done.
        #
        # Arguments:
        #
        #  do_element:  Has three input arguments:
        #                element     node being processed
        #                fate     fate -- we return fate (libmap)
        #                libmap   result accumulator (frozenlib_tome_set, NakedCOMPILEDFILEInfoSet) 
        #            do_element should side-effect stuff into 'm' as appropriate, then return fate (libmap)
        #  [...]     list being processed
        #  fate      Fate: When we're done, we return fate (libmap)
        #  libmap    Initially empty (frozenlib_tome_set, NakedCOMPILEDFILEInfoSet) pair in which we accumulate stuff

        fun do_list do_element []      fate libmap
                =>
                fate libmap;

            do_list do_element (h ! t) fate libmap
                =>
                do_element h (do_list do_element t fate) libmap;
        end;

        # This fn provides a very general way of iterating over
        # a inter_library_dependency_graph, accumulating some sort
        # of per-node information.
        #
        # We are passed a first argument containing:
        # o  A way of extracting useful info from a frozenlib_tome node:     a7fileInfo: FreezefileInfo::info -> A_element
        # o  A way of extracting useful info from a Thawedlib_Tome node:  thawedlib_tome: thawedlib_tome::info -> A_element,
        # o  An empty container in which to put such info elements:    Nil: A_elements
        # o  A way of adding such an element to such a container:      Cons: A_element * A_elements -> A_elements
        #
        # Our second argument is the
        # (root node of the) inter_library_dependency_graph
        # to process.
        #
        # Our return value is the resulting containerful of elements.
        #
        fun scan_dependency_graph { nil, ... } lg::BAD_LIBRARY
                =>
                nil;

            scan_dependency_graph x (g as lg::LIBRARY { catalog, ... } )
                =>
                {   x ->  { a7file_info, thawedlib_tome, cons, nil };

                    # For a intra_library_dependency_graph a7fileInfo (freezefile) node,
                    # we need to process both 'near_imports' and 'far_imports'.
                    #
                    # If we've already seen this node, we return fate (libmap) immediately.
                    #
                    # Otherwise:
                    #
                    # First, we iterate recursively down near_imports via do_list,
                    # calling ourself (doCompiled_FileNode) recursively one each element.
                    #
                    # Second, we call ourself recursively on each of our
                    # global imports, again via do_list.
                    #
                    # Third, we add ourself via register_stable_library
                    # to our running list of processed compiled_files,
                    # so we won't process it again.
                    #
                    # Fourth, call our fate, getting back in return
                    # the Cons()-ed up client container value result so far.
                    #
                    # Fifth and last, we extract the client-desired info
                    # from our node, Cons it into the client-provided container,
                    # and return the thus-augmented container.
                    #
                    # NB: Since all kids of a freezefile must
                    # themselves be stable libraries, we have no
                    # doSourcefileNode cases from here on down.
                    #
                    fun do_frozen_compilable  (sg::FROZENLIB_TOME_TIN tome_tin)  fate  libmap
                        =
                        {   tome_tin ->   { frozenlib_tome   => file_info,
                                            near_imports,
                                            far_import_thunks
                                          };


                            fun fate' libmap
                                =
                                cons ( a7file_info file_info,
                                       fate (register_stable_library (libmap, file_info))
                                     );

                            if (freezefile_is_registered (libmap, file_info))
                                #                           
                                fate libmap;
                            else
                                do_list
                                    do_frozen_compilable                                # Per-node fn.        
                                    near_imports                                # List to process.    
                                    (do_list                            # Fate.       
                                        do_lazy_far_compiled_file_node
                                            far_import_thunks
                                            fate'
                                    )
                                    libmap;                             # Result accumulator. 
                            fi;
                        }

                    also
                    fun do_far_compiled_file_node (tome: sg::Far_Frozenlib_Tome)
                        =
                        do_frozen_compilable  tome.frozenlib_tome_tin

                    also
                    fun do_lazy_far_compiled_file_node  thunk
                        =
                        do_far_compiled_file_node (thunk ());


                    # For a intra_library_dependency_graph thawedlib_tome node,
                    # we need to register all near_imports
                    # directly via register_source_file, then process
                    # all far_imports via recursive
                    # calls to our toplevel 'doFarSourcefileOrFreezefileNode' fn:
                    #
                    fun do_thawedlib_tome (sg::THAWEDLIB_TOME_TIN tome_tin) fate libmap
                        =
                        {   tome_tin ->   { thawedlib_tome   => file_info,
                                            near_imports,
                                            far_imports
                                          };


                            fun fate' libmap
                                =
                                cons (thawedlib_tome file_info, fate (register_source_file (libmap, file_info)));

                            if (sml_file_is_registered (libmap, file_info))
                                #                           
                                fate libmap;
                            else
                                do_list
                                    do_thawedlib_tome                                                   # Per-node fn.        
                                    near_imports                                                        # List to process.    
                                    (do_list
                                        do_bare_or_frozen_compilable
                                        far_imports
                                        fate'
                                    )                                                           # Fate.       
                                    libmap;                                                     # Result accumulator. 
                            fi;
                        }

                    # Iterate over everything reachable from a
                    # toplevel intra_library_dependency_graph node.
                    # Our argument may be a frozenlib_tome or thawedlib_tome
                    # node --  figure out which and delegate accordingly:
                    #
                    also
                    fun   do_bare_or_frozen_compilable { tome_tin => sg::TOME_IN_FROZENLIB tome, ... }
                              =>
                              do_frozen_compilable  tome.frozenlib_tome_tin;

                          do_bare_or_frozen_compilable { tome_tin => sg::TOME_IN_THAWEDLIB thawedlib_tome, ... }
                              =>
                              do_thawedlib_tome   thawedlib_tome;
                    end;

                    # We're called once for each (thunk) value exported
                    # by the inter_library_dependency_graph.  Force the thunk and hand
                    # off the result to 'doFarSourcefileOrFreezefileNode' to process:
                    #
                    fun do_compiledfile (compiledfile: lg::Fat_Tome)
                        =
                        do_bare_or_frozen_compilable (compiledfile.masked_tome_thunk ());

                    # Top level consists of applying import_export above to
                    # the inter_library_dependency_graph's 'catalog' symbol map's values: 
                    #
                    do_list
                        do_compiledfile
                        (symbol_map::vals_list  catalog)
                        (\\ _ = nil)
                        (frozenlib_tome_set::empty, thawedlib_tome_set::empty);

                };                                      # fun scan_dependency_graph 
        end;
    };
end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext