## 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.pkgstipulate
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.pkgherein
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;